share/hedgewars/Data/Maps/CTF_Blizzard/map.lua
author Wuzzy <Wuzzy2@mail.ru>
Tue, 21 Aug 2018 17:56:17 +0200
changeset 13680 d3a4cbba060e
parent 13648 690cc84e9fd6
child 13692 a8b2a5e7e9db
permissions -rw-r--r--
Consistently rename "team chat" to "clan chat" (except chat command) Only change in strings, no functional change. "Team" and "clan" have defined meanings in HW, but "team chat" oddly broke this convention. This feature allows chat with your clan, not with your team, so is now called "clan chat". /team command unchanged to avoid disruption (for now).

-------------------------------
-- CTF_BLIZZARD 0.9
--------------------------------

---------
-- 0.2
---------

-- disabled super weapons

-- theme modifications

-- improved hog placement system: teams can now be put
-- in any order and be of any size

---------
-- 0.3
---------

-- In this version:

-- changed starting weapons
-- changed crate drop contents and rate of drops

-- completely removed super weapons and super weapon scripts

-- removed custom respawning
-- removed set respawn points

-- added AIRespawn-esque respawning
-- added simple left vs right respawn points

-- added non-lethal poison to flag carriers as an indicator

-- improved flag mechanics and player-flag feedback
-- flag now instantly respawns if you kill enemy hog and return it,
-- or if the flag falls in water, _BUT_ not if it is blown up

---------
-- 0.4
---------

-- tweaked crate drop rates and crate contents
-- improved the teleporters, they should now be able to handle rope... hopefully
-- updated SetEffect calls to be in line with 0.9.15 definitions
-- added visual gears when hogs respawn
-- added visual gears when hogs teleport
-- added visual gear to track flag and flag carriers
-- removed poisoning of flag carriers
-- removed health adjustments for flag carriers due to aforementioned poisons

---------
-- 0.5
---------

-- added translation support, hopefully
-- added ctf rules
-- added effects to the teleporters
-- added aura round spawning area
-- changed the aura around the flag carrier / flag to an aura and added some support for this
-- changed things so the seed is no longer always the same...

---------
-- 0.6
---------

-- removed branding and version number
-- removed teleport from starting weapons
-- increased captures to 3

------------
-- 0.7
------------

-- hopefully fixed a bug with the teleporters
-- added a fix for crate possibly getting imbedded in land when it was near the water line

------------
-- 0.8
------------

-- fixed version control fail with missing check on onGearDelete

-- changed hog placements code so that they start in the same place for both teams
-- and hogs move in the same order, not backwards to each other.

-----------
-- 0.9
------------

-- add support for more players
-- re-enable sudden death, but set water rise to 0

HedgewarsScriptLoad("/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 actionReset = 0 -- used in CheckTeleporters()

local roundsCounter = 0	-- used to determine when to spawn more crates
						-- currently every 6 TURNS, should this work
						-- on ROUNDS instead?
local effectTimer = 0

local ropeGear = nil

--------------------------
-- hog and team tracking variales
--------------------------

local numhhs = 0 -- store number of hedgehogs
local hhs = {} -- store hedgehog gears

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
local clanTeams = {} -- list of teams per clan

-------------------
-- flag variables
-------------------

local fGear = {}	-- pointer to the case gears that represent the flag
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 fSpawnC = {}
local fCirc = {} -- flag/carrier marker circles
local fCol = {} -- colour of the clans

local vCircX = {}
local vCircY = {}
local vCircMinA = {}
local vCircMaxA = {}
local vCircType = {}
local vCircPulse = {}
local vCircFuckAll = {}
local vCircRadius = {}
local vCircWidth = {}
local vCircCol = {}


--------------------------------
--zone and teleporter variables
--------------------------------

local redTel
local orangeTel

local zXMin = {}
local zWidth = {}
local zYMin = {}
local zHeight = {}
local zOccupied = {}
local zCount = 0

------------------------
-- zone methods
------------------------
-- see on gameTick also

function ManageTeleporterEffects()
	effectTimer = effectTimer + 1
	if effectTimer > 50 then
		effectTimer = 0

		for i = 0,1 do
			local eX = 10 + zXMin[i] + GetRandom(zWidth[i]-10)
			local eY = 50 + zYMin[i] + GetRandom(zHeight[i]-110)

			-- steam and smoke and DUST look good, smokering looks trippy
			-- smoketrace and eviltrace are not effected by wind?
			-- chunk is a LR falling gear
			local tempE = AddVisualGear(eX, eY, vgtDust, 0, false)
			if tempE ~= 0 then
				SetVisualGearValues(tempE, eX, eY, nil, nil, nil, nil, nil, nil, nil, fCol[i])
			end
		end
	end
end

function CreateZone(xMin, yMin, width, height)


	zXMin[zCount] = xMin
	zYMin[zCount] = yMin
	zWidth[zCount] = width
	zHeight[zCount] = height
	zOccupied[zCount] = false
	zCount = zCount + 1

	return (zCount-1)

end

function GearIsInZone(gear, zI)

	if (GetX(gear) > zXMin[zI]) and (GetX(gear) < (zXMin[zI]+zWidth[zI])) and (GetY(gear) > zYMin[zI]) and (GetY(gear) < (zYMin[zI]+zHeight[zI])) then
		zOccupied[zI] = true
	else
		zOccupied[zI] = false
	end

	return zOccupied[zI]

end

------------------------
--flag methods
------------------------

function CheckScore(teamID)

	local alt
	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 GetHogClan(hhs[i]) == alt then
				SetEffect(hhs[i], heResurrectable, 0)
				SetHealth(hhs[i],0)
			end
		end
		ShowMission(loc("GAME OVER!"), loc("Victory for the ") .. GetHogTeamName(CurrentHedgehog), loc("Hooray!"), 0, 0)
	end

end

function HandleRespawns()

	for i = 0, 1 do

		if fNeedsRespawn[i] == true then
			fGear[i] = SpawnFakeAmmoCrate(fSpawnX[i],fSpawnY[i],false,false)
			--fGear[i] = SpawnHealthCrate(fSpawnX[i],fSpawnY[i])
			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 FlagDeleted(gear)

	local wtf, bbq
	PlaySound(sndShotgunReload)
	if (gear == fGear[0]) then
		wtf = 0
		bbq = 1
	elseif (gear == fGear[1]) then
		wtf = 1
		bbq = 0
	end

	if CurrentHedgehog ~= nil then

		--if the player picks up the flag
		if CheckDistance(CurrentHedgehog, fGear[wtf]) < 1600 then

			fGear[wtf] = nil -- the flag has now disappeared and we shouldnt be pointing to it

			-- player has successfully captured the enemy flag
			if (GetHogClan(CurrentHedgehog) == wtf) and (CurrentHedgehog == fThief[bbq]) and (fIsMissing[wtf] == false) then
				fIsMissing[wtf] = false
				fNeedsRespawn[wtf] = true
				fIsMissing[bbq] = false
				fNeedsRespawn[bbq] = true
				fCaptures[wtf] = fCaptures[wtf] +1

				AddCaption(string.format(loc("%s has scored!"), GetHogTeamName(CurrentHedgehog)), capcolDefault, capgrpGameState)
				for i=1, #clanTeams[wtf] do
					SetTeamLabel(clanTeams[wtf][i], fCaptures[wtf])
				end

				PlaySound(sndHomerun)
				fThief[bbq] = nil -- player no longer has the enemy flag
				CheckScore(wtf)

			--if the player is returning the flag
			elseif GetHogClan(CurrentHedgehog) == wtf then

				fNeedsRespawn[wtf] = true

				-- NEW ADDIITON, does this work? Should make it possible to return your flag and then score in the same turn
				if fIsMissing[wtf] == true then
					HandleRespawns() -- this will set fIsMissing[wtf] to false :)
					AddCaption(loc("Flag returned!"))
				elseif fIsMissing[wtf] == false then
					AddCaption(loc("That was pointless. The flag will respawn next round."))
				end

			--if the player is taking the enemy flag
			elseif GetHogClan(CurrentHedgehog) == bbq then
				fIsMissing[wtf] = true
				for i = 0,numhhs-1 do
					if CurrentHedgehog == hhs[i] then
						fThief[wtf] = hhs[i]
					end
				end

				AddCaption(loc("Flag captured!"))

			else --below line doesnt usually get called
				AddCaption("Hmm... that wasn't supposed to happen...")

			end

		-- if flag has been destroyed, probably
		else

			if GetY(fGear[wtf]) > 2025 then
				fGear[wtf] = nil
				fIsMissing[wtf] = true
				fNeedsRespawn[wtf] = true
				HandleRespawns()
			else
				fGear[wtf] = nil
				fIsMissing[wtf] = true
				fNeedsRespawn[wtf] = true
				AddCaption(loc("Boom!") .. " " .. loc("The flag will respawn next round."))
			end

		end

	-- if flag has been destroyed deep underwater and player is now nil
	-- probably only gets called if the flag thief drowns himself
	-- otherwise the above one will work fine
	else
		fGear[wtf] = nil
		fIsMissing[wtf] = true
		fNeedsRespawn[wtf] = true
		AddCaption(loc("The flag will respawn next round."))
	end

end

function FlagThiefDead(gear)

	local wtf, bbq
	if (gear == fThief[0]) then
		wtf = 0
		bbq = 1
	elseif (gear == fThief[1]) then
		wtf = 1
		bbq = 0
	end

	if fThief[wtf] ~= nil then
		
		if fThiefY[wtf] > 2040 then
			fGear[wtf] = SpawnFakeAmmoCrate(fThiefX[wtf],(fThiefY[wtf]+10),false,false)
		else
			fGear[wtf] = SpawnFakeAmmoCrate(fThiefX[wtf],(fThiefY[wtf]-50),false,false)
		end

		AddVisualGear(fThiefX[wtf], fThiefY[wtf], vgtBigExplosion, 0, false)
		fThief[wtf] = nil
	end

end

function HandleCircles()

	for i = 0, 1 do
		if fIsMissing[i] == false then -- draw a circle at the flag's spawning place
			SetVisualGearValues(fCirc[i], fSpawnX[i],fSpawnY[i], vCircMinA[i], vCircMaxA[i], vCircType[i], vCircPulse[i], vCircFuckAll[i], vCircRadius[i], vCircWidth[i], vCircCol[i])
		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], vCircMinA[i], vCircMaxA[i], vCircType[i], vCircPulse[i], vCircFuckAll[i], vCircRadius[i], vCircWidth[i], vCircCol[i])
			elseif fThief[i] == nil then -- draw cirle round dropped flag
				SetVisualGearValues(fCirc[i], GetX(fGear[i]),GetY(fGear[i]), vCircMinA[i], vCircMaxA[i], vCircType[i], vCircPulse[i], vCircFuckAll[i], vCircRadius[i], vCircWidth[i], vCircCol[i])
			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])
		end
	end

end

------------------------
-- general methods
------------------------

function CheckDistance(gear1, gear2)

	local g1X, g1Y = GetGearPosition(gear1)
	local g2X, g2Y = GetGearPosition(gear2)

	g1X = g1X - g2X
	g1Y = g1Y - g2Y
	local dist = (g1X*g1X) + (g1Y*g1Y)

	return dist

end

function CheckTeleporters()

	local teleportActive = false

	if (GearIsInZone(CurrentHedgehog, redTel) == true) and (GetHogClan(CurrentHedgehog) == 0) then
		teleportActive = true
		destinationX = 1402
		destinationY = 321
	elseif (GearIsInZone(CurrentHedgehog, orangeTel) == true) and (GetHogClan(CurrentHedgehog) == 1) then
		teleportActive = true
		destinationX = 2692
		destinationY = 321
	end

	if teleportActive == true then
		if actionReset == 0 then
			if ropeGear ~= nil then
				if GetGearElasticity(ropeGear) ~= 0 then
					SetGearMessage(CurrentHedgehog, gmAttack)
				end
			end
		elseif actionReset == 10 then
			SetGearMessage(CurrentHedgehog, 0)
		elseif actionReset == 20 then
			AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtBigExplosion, 0, false)
			SetGearPosition(CurrentHedgehog,destinationX,destinationY)
			AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtBigExplosion, 0, false)
		end

		actionReset = actionReset + 1
		if actionReset >= 30 then
			actionReset = 0
		end

	end

end

function RebuildTeamInfo()


	-- make a list of individual team names
	for i = 0, (TeamsCount-1) do
		teamNameArr[i] = GetTeamName(i)
		teamSize[i] = 0
		teamIndex[i] = 0
		SetTeamLabel(teamNameArr[i], "0")
	end

	-- find out how many hogs per team, and the index of the first hog in hhs
	for i = 0, TeamsCount-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

				local clan = GetHogClan(hhs[z])
				-- Also remember the clan to which the team belongs to
				if not clanTeams[clan] then
					clanTeams[clan] = {}
				end
				table.insert(clanTeams[clan], teamNameArr[i])
			end
		end


	end

end

function HandleCrateDrops()

	roundsCounter = roundsCounter +1

	if roundsCounter == 5 then

		roundsCounter = 0

		r = GetRandom(8)
		if r == 0 then
			SpawnSupplyCrate(0,0,amSwitch)
		elseif r == 1 then
			SpawnSupplyCrate(0,0,amTeleport)
		elseif r == 2 then
			SpawnSupplyCrate(0,0,amJetpack)
		elseif r == 3 then
			SpawnSupplyCrate(0,0,amExtraTime)
		elseif r == 4 then
			SpawnSupplyCrate(0,0,amGirder)
		elseif r == 5 then
			SpawnSupplyCrate(0,0,amDynamite)
		elseif r == 6 then
			SpawnSupplyCrate(0,0,amFlamethrower)
		elseif r == 7 then
			SpawnSupplyCrate(0,0,amPortalGun)
		end

	end

end

------------------------
-- game methods
------------------------

function onGameInit()

	-- Things we don't modify here will use their default values.
	GameFlags = gfDivideTeams -- Game settings and rules
	TurnTime = 30000 -- The time the player has to move each round (in ms)
	CaseFreq = 0 -- The frequency of crate drops
	MinesNum = 0 -- The number of mines being placed
	Explosives = 0 -- The number of explosives being placed
	-- Disable Sudden Death
	WaterRise = 0
	HealthDecrease = 0
	Map = "Blizzard" -- The map to be played
	Theme = "Snow" -- The theme to be used

end


function onGameStart()

	ShowMission(loc("CTF_Blizzard"), loc("Capture The Flag"), 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)


	-- initialize teleporters
	redTel = CreateZone(342,1316,42,449)	-- red teleporter
	orangeTel = CreateZone(3719,1330,45,449)	-- orange teleporter


	--new improved placement schematics aw yeah
	RebuildTeamInfo()
	local team1Placed = 0
	local team2Placed = 0
	for i = 0, (TeamsCount-1) do
		for g = teamIndex[i], (teamIndex[i]+teamSize[i]-1) do
			if GetHogClan(hhs[g]) == 0 then
				SetGearPosition(hhs[g],1403+ ((team1Placed+1)*50),1570)
				team1Placed = team1Placed +1
				if team1Placed > 6 then
					team1Placed = 0
				end
			elseif GetHogClan(hhs[g]) == 1 then
				SetGearPosition(hhs[g],2691- ((team2Placed+1)*50),1570)
				team2Placed = team2Placed +1
				if team2Placed > 6 then
					team2Placed = 0
				end
			end
		end
	end



	--spawn starting ufos and or super weapons
	SpawnSupplyCrate(2048,1858,amJetpack)

	--set flag spawn points and spawn the flags
	fSpawnX[0] = 957
	fSpawnY[0] = 1747
	fSpawnX[1] = 3123
	fSpawnY[1] = 1747

	for i = 0, 1 do
		fGear[i] = SpawnFakeAmmoCrate(fSpawnX[i],fSpawnY[i],false,false)
		fCirc[i] = AddVisualGear(fSpawnX[i],fSpawnY[i],vgtCircle,0,true)
		fCol[i] = GetClanColor(i)

		fSpawnC[i] = AddVisualGear(fSpawnX[i],fSpawnY[i],vgtCircle,0,true)
		SetVisualGearValues(fSpawnC[i], fSpawnX[i],fSpawnY[i], 10, 200, 1, 10, 0, 300, 5, fCol[i])


		fIsMissing[i] = false
		fNeedsRespawn[i] = false
		fCaptures[i] = 0

		vCircMinA[i] = 20
		vCircMaxA[i] = 255
		vCircType[i] = 1
		vCircPulse[i] = 10
		vCircFuckAll[i] = 0
		vCircRadius[i] = 150
		vCircWidth[i] = 5
		vCircCol[i] = fCol[i]

		SetVisualGearValues(fCirc[i], fSpawnX[i],fSpawnY[i], vCircMinA[i], vCircMaxA[i], vCircType[i], vCircPulse[i], vCircFuckAll[i], vCircRadius[i], vCircWidth[i], vCircCol[i])

	end

end


function onNewTurn()

	HandleRespawns()
	HandleCrateDrops()

end

function onGameTick()

	-- onRessurect calls AFTER you have resurrected,
	-- so keeping track of x,y a few milliseconds before
	-- is useful

	for i = 0,1 do
		if fThief[i] ~= nil then
			fThiefX[i] = GetX(fThief[i])
			fThiefY[i] = GetY(fThief[i])
		end
	end

	-- things we wanna check often
	if (CurrentHedgehog ~= nil) then
		CheckTeleporters()
	end

	HandleCircles()
	ManageTeleporterEffects()

end


function onAmmoStoreInit()

	SetAmmo(amDrill,9,0,0,0)
	SetAmmo(amMortar,9,0,0,0)

	SetAmmo(amGrenade,9,0,0,0)
	SetAmmo(amClusterBomb,4,0,0,0)

	SetAmmo(amShotgun, 9, 0, 0, 0)
	SetAmmo(amFlamethrower, 1, 0, 0, 1)

	SetAmmo(amFirePunch, 9, 0, 0, 0)
	SetAmmo(amBaseballBat, 2, 0, 0, 0)

	SetAmmo(amDynamite,2,0,0,1)
	SetAmmo(amSMine,4,0,0,0)

	SetAmmo(amBlowTorch, 9, 0, 0, 0)
	SetAmmo(amPickHammer, 9, 0, 0, 0)
	SetAmmo(amGirder, 2, 0, 0, 2)
	SetAmmo(amPortalGun, 2, 0, 0, 2)

	SetAmmo(amParachute, 9, 0, 0, 0)
	SetAmmo(amRope, 9, 0, 0, 0)
	SetAmmo(amTeleport, 0, 0, 0, 1)
	SetAmmo(amJetpack, 1, 0, 0, 1)

	SetAmmo(amSwitch, 2, 0, 0, 1)
	SetAmmo(amExtraTime,1,0,0,1)
	SetAmmo(amLowGravity,1,0,0,0)
	SetAmmo(amSkip, 9, 0, 0, 0)

end


function onGearResurrect(gear, vGear)

	-- 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

	-- place hogs belonging to each clan either left or right side of map
	if GetHogClan(gear) == 0 then
		FindPlace(gear, false, 0, 2048)
	elseif GetHogClan(gear) == 1 then
		FindPlace(gear, false, 2048, LAND_WIDTH)
	end

	if vGear then
		SetVisualGearValues(vGear, GetX(gear), GetY(gear))
	end

end

local excessHogsWarning = false

function onGearAdd(gear)

	if GetGearType(gear) == gtHedgehog then

		if GetHogClan(gear) > 1 then
			DeleteGear(gear)
			if not excessHogsWarning then
				WriteLnToChat(loc("Only two clans allowed! Excess hedgehogs will be removed."))
				excessHogsWarning = true
			end
		else
			hhs[numhhs] = gear
			numhhs = numhhs + 1
			SetEffect(gear, heResurrectable, 1)
		end

	elseif GetGearType(gear) == gtRope then
		ropeGear = gear
	end

end

function onGearDelete(gear)

	if (gear == fGear[0]) or (gear == fGear[1]) then
		FlagDeleted(gear)
	end

	if GetGearType(gear) == gtRope then
		ropeGear = nil
	end

	if GetGearType(gear) == gtHedgehog then
		for i = 0, (numhhs-1) do
			if gear == hhs[i] then
				
				for k = 0,1 do
					if gear == fThief[k] then
						FlagThiefDead(gear)
					end
				end				
				hhs[i] = nil	
			end		
		end
	end

end