share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua
changeset 13711 0da36902e5b6
parent 13710 e2b1abb4fba5
child 13712 d5f12b1d180d
equal deleted inserted replaced
13710:e2b1abb4fba5 13711:0da36902e5b6
    87 --------------------------
    87 --------------------------
    88 -- imitate winning animation at end instead of just ending the game
    88 -- imitate winning animation at end instead of just ending the game
    89 
    89 
    90 -- add support for other world edges (they are currently disabled)
    90 -- add support for other world edges (they are currently disabled)
    91 
    91 
    92 -- maybe add a check for a tie, IMPOSSIBRU THERE ARE NO TIES
       
    93 
       
    94 -- if more weapons are added, replace primshotsfired all over the place
    92 -- if more weapons are added, replace primshotsfired all over the place
    95 
    93 
    96 -- look for derp and let invaders shoot again
    94 -- look for derp and let invaders shoot again
    97 
    95 
    98 -- more weapons? flamer/machineballgun,
    96 -- more weapons? flamer/machineballgun,
   146 -- gaudyRacer
   144 -- gaudyRacer
   147 SI.boosterOn = false
   145 SI.boosterOn = false
   148 SI.preciseOn = false
   146 SI.preciseOn = false
   149 SI.roundLimit = 3		-- can be overridden by script parameter "rounds"
   147 SI.roundLimit = 3		-- can be overridden by script parameter "rounds"
   150 SI.roundNumber = 0
   148 SI.roundNumber = 0
   151 SI.firstClan = 10
   149 SI.lastRound = -1
   152 SI.gameOver = false
   150 SI.gameOver = false
   153 SI.gameBegun = false
   151 SI.gameBegun = false
   154 
       
   155 SI.bestClan = 65535
       
   156 SI.bestScore = 0
       
   157 
   152 
   158 -- for script parameters
   153 -- for script parameters
   159 -- NOTE: If you change this, also change the default “Space Invasion” game scheme
   154 -- NOTE: If you change this, also change the default “Space Invasion” game scheme
   160 SI.startBarrels = 5		-- "barrels"
   155 SI.startBarrels = 5		-- "barrels"
   161 SI.startShield = 30		-- "shield"
   156 SI.startShield = 30		-- "shield"
   170 --------------------------
   165 --------------------------
   171 
   166 
   172 SI.numhhs = 0
   167 SI.numhhs = 0
   173 SI.hhs = {}
   168 SI.hhs = {}
   174 
   169 
   175 SI.numTeams = 0
       
   176 SI.teamNameArr = {}
   170 SI.teamNameArr = {}
       
   171 SI.teamNameArrReverse = {}
   177 SI.teamClan = {}
   172 SI.teamClan = {}
   178 SI.teamSize = {}
   173 SI.teamSize = {}
   179 SI.teamIndex = {}
   174 SI.teamIndex = {}
   180 
   175 
   181 SI.teamScore = {}
   176 SI.teamScore = {}
   388 		SI.teamIndex[i] = 0
   383 		SI.teamIndex[i] = 0
   389 		SI.teamScore[i] = 0
   384 		SI.teamScore[i] = 0
   390 		SI.teamCircsKilled[i] = 0
   385 		SI.teamCircsKilled[i] = 0
   391 		SI.teamSurfer[i] = false
   386 		SI.teamSurfer[i] = false
   392 	end
   387 	end
   393 	SI.numTeams = 0
   388 
   394 
   389 	for i=0, TeamsCount-1 do
   395 	for i = 0, (SI.numhhs-1) do
   390 
   396 
   391 		local name = GetTeamName(i)
   397 		local z = 0
   392 		SI.teamNameArr[i] = name
   398 		local unfinished = true
   393 		SI.teamNameArrReverse[name] = i
   399 		while(unfinished == true) do
       
   400 
       
   401 			local newTeam = true
       
   402 			local tempHogTeamName = GetHogTeamName(SI.hhs[i]) -- this is the new name
       
   403 
       
   404 			if tempHogTeamName == SI.teamNameArr[z] then
       
   405 				newTeam = false
       
   406 				unfinished = false
       
   407 			end
       
   408 
       
   409 			z = z + 1
       
   410 
       
   411 			if z == (TeamsCount-1) then
       
   412 				unfinished = false
       
   413 				if newTeam == true then
       
   414 					SI.teamNameArr[SI.numTeams] = tempHogTeamName
       
   415 					SI.numTeams = SI.numTeams + 1
       
   416 				end
       
   417 			end
       
   418 
       
   419 		end
       
   420 
   394 
   421 	end
   395 	end
   422 
   396 
   423 	-- find out how many hogs per team, and the index of the first hog in SI.hhs
   397 	-- find out how many hogs per team, and the index of the first hog in SI.hhs
   424 	for i = 0, (TeamsCount-1) do
   398 	for i = 0, (TeamsCount-1) do
   498 		newAward = oldAward
   472 		newAward = oldAward
   499 	end
   473 	end
   500 	return newAward
   474 	return newAward
   501 end
   475 end
   502 
   476 
       
   477 -- Update scoreboard and check victory state.
       
   478 -- Returns 2 bools:
       
   479 -- 1: true if game over
       
   480 -- 2: true if game's not over but we're playing now in tie-breaking phase
       
   481 
   503 function CommentOnScore()
   482 function CommentOnScore()
   504 	local teamStats = {}
   483 	local teamStats = {}
   505 	for i = 0,(TeamsCount-1) do
   484 	for i = 0,(TeamsCount-1) do
   506 		table.insert(teamStats, {score = SI.teamScore[i], kills = SI.teamCircsKilled[i], name = SI.teamNameArr[i]})
   485 		table.insert(teamStats, {score = SI.teamScore[i], kills = SI.teamCircsKilled[i], name = SI.teamNameArr[i]})
   507 	end
   486 	end
   519 		local comment
   498 		local comment
   520 		if teamStats[i].name ~= " " then
   499 		if teamStats[i].name ~= " " then
   521 			local comment = teamStats[i].name .. " |" ..
   500 			local comment = teamStats[i].name .. " |" ..
   522 			string.format(loc("Score: %d"), teamStats[i].score) .. "|" ..
   501 			string.format(loc("Score: %d"), teamStats[i].score) .. "|" ..
   523 			string.format(loc("Kills: %d"), teamStats[i].kills)
   502 			string.format(loc("Kills: %d"), teamStats[i].kills)
   524 			if i < TeamsCount then	
   503 			if i < TeamsCount then
   525 				comment = comment .. "| |"
   504 				comment = comment .. "| |"
   526 			end
   505 			end
   527 			table.insert(teamComment, comment)
   506 			table.insert(teamComment, comment)
   528 
   507 
   529 			SendStat(siClanHealth, tostring(teamStats[i].score), teamStats[i].name)
   508 			SendStat(siClanHealth, tostring(teamStats[i].score), teamStats[i].name)
   531 			comment = "|"
   510 			comment = "|"
   532 		end
   511 		end
   533 		table.insert(teamComment, comment)
   512 		table.insert(teamComment, comment)
   534 	end
   513 	end
   535 
   514 
       
   515 	local roundLimitHit = SI.roundNumber >= SI.roundLimit
       
   516 	local tie = teamStats[1].score == teamStats[2].score
       
   517 	local lGameOver = roundLimitHit and (not tie)
       
   518 
   536 	local entireC = ""
   519 	local entireC = ""
       
   520 
   537 	for i = TeamsCount,1,-1 do
   521 	for i = TeamsCount,1,-1 do
   538 		entireC = entireC .. teamComment[i]
   522 		entireC = entireC .. teamComment[i]
   539 	end
   523 	end
       
   524 
   540 	local statusText, scoreText
   525 	local statusText, scoreText
   541 	if SI.roundNumber >= SI.roundLimit then
   526 	-- Game is over
       
   527 	if lGameOver then
   542 		statusText = loc("Game over!")
   528 		statusText = loc("Game over!")
   543 		scoreText = loc("Final team scores:")
   529 		scoreText = loc("Final team scores:")
   544 	else
   530 	-- Round is over and game is not yet complete
       
   531 	elseif not roundLimitHit then
   545 		AddCaption(string.format(loc("Rounds complete: %d/%d"), SI.roundNumber, SI.roundLimit), capcolDefault, capgrpMessage)
   532 		AddCaption(string.format(loc("Rounds complete: %d/%d"), SI.roundNumber, SI.roundLimit), capcolDefault, capgrpMessage)
   546 		return
   533 		return lGameOver, false
   547 	end
   534 	-- Teams are tied for the lead at the end
       
   535 	elseif roundLimitHit and tie then
       
   536 		local tieBreakingRound = SI.roundNumber - SI.roundLimit + 1
       
   537 		local msg
       
   538 		if tieBreakingRound == 1 then
       
   539 			msg = loc("Teams are tied! Continue playing rounds until we have a winner!")
       
   540 		else
       
   541 			msg = string.format(loc("Tie-breaking round %d"), tieBreakingRound)
       
   542 		end
       
   543 		AddCaption(msg, capcolDefault, capgrpMessage)
       
   544 		return lGameOver, true
       
   545 	end
       
   546 
   548 	local displayTime
   547 	local displayTime
   549 	if SI.roundNumber >= SI.roundLimit then
   548 	if lGameOver then
   550 		displayTime = 20000
   549 		displayTime = 20000
   551 	else
   550 	else
   552 		displayTime = 1
   551 		displayTime = 1
   553 	end
   552 	end
   554 	ShowMission(	loc("Space Invasion"),
   553 	ShowMission(	loc("Space Invasion"),
   555 			statusText,
   554 			statusText,
   556 			string.format(loc("Rounds complete: %d/%d"), SI.roundNumber, SI.roundLimit) .. "| " .. "|" ..
   555 			string.format(loc("Rounds complete: %d/%d"), SI.roundNumber, SI.roundLimit) .. "| " .. "|" ..
   557 			scoreText .. " |" ..entireC, 4, displayTime)
   556 			scoreText .. " |" ..entireC, 4, displayTime)
   558 
   557 
   559 	if SI.roundNumber >= SI.roundLimit then
   558 	if lGameOver then
   560 		local winnerTeam = teamStats[1].name
   559 		local winnerTeam = teamStats[1].name
   561 		for i = 0, (SI.numhhs-1) do
   560 		for i = 0, (SI.numhhs-1) do
   562 			if GetHogTeamName(SI.hhs[i]) == winnerTeam then
   561 			if GetHogTeamName(SI.hhs[i]) == winnerTeam then
   563 				SetState(SI.hhs[i], bor(GetState(SI.hhs[i]), gstWinner))
   562 				SetState(SI.hhs[i], bor(GetState(SI.hhs[i]), gstWinner))
   564 			end
   563 			end
   581 
   580 
   582 
   581 
   583 --[[ Award some awards (just for fun, its for the stats screen only
   582 --[[ Award some awards (just for fun, its for the stats screen only
   584 and has no effect on the score or game outcome. ]]
   583 and has no effect on the score or game outcome. ]]
   585 		local awardsGiven = 0
   584 		local awardsGiven = 0
   586 	
   585 
       
   586 		if SI.roundNumber == SI.roundLimit + 1 then
       
   587 			SendStat(siCustomAchievement,
       
   588 			loc("The teams were tied, so an additional round has been played to determine the winner."))
       
   589 			awardsGiven = awardsGiven + 1
       
   590 		elseif SI.roundNumber > SI.roundLimit then
       
   591 			SendStat(siCustomAchievement,
       
   592 			string.format(loc("The teams were tied, so %d additional rounds have been played to determine the winner."),
       
   593 			SI.roundNumber - SI.roundLimit))
       
   594 			awardsGiven = awardsGiven + 1
       
   595 		end
   587 		if SI.awardTotalKills >= 30 then
   596 		if SI.awardTotalKills >= 30 then
   588 			awardsGiven = awardsGiven + 1
   597 			awardsGiven = awardsGiven + 1
   589 			SendStat(siCustomAchievement,
   598 			SendStat(siCustomAchievement,
   590 				string.format(loc("%d invaders have been destroyed in this game."), SI.awardTotalKills))
   599 				string.format(loc("%d invaders have been destroyed in this game."), SI.awardTotalKills))
   591 		end
   600 		end
   681 			if r == 1 then text = loc("This game wasn’t really exciting.")
   690 			if r == 1 then text = loc("This game wasn’t really exciting.")
   682 			elseif r == 2 then text = loc("Did I miss something?")
   691 			elseif r == 2 then text = loc("Did I miss something?")
   683 			elseif r == 3 then text = loc("Nothing of interest has happened.")
   692 			elseif r == 3 then text = loc("Nothing of interest has happened.")
   684 			elseif r == 4 then text = loc("There are no snarky comments this time.")
   693 			elseif r == 4 then text = loc("There are no snarky comments this time.")
   685 			end
   694 			end
   686 		
   695 
   687 			SendStat(siCustomAchievement, text)
   696 			SendStat(siCustomAchievement, text)
   688 		end
   697 		end
   689 	end
   698 	end
       
   699 
       
   700 	return lGameOver, false
   690 end
   701 end
   691 
   702 
   692 function onNewRound()
   703 function onNewRound()
       
   704 	SI.lastRound = TotalRounds
   693 	SI.roundNumber = SI.roundNumber + 1
   705 	SI.roundNumber = SI.roundNumber + 1
   694 
   706 
   695 	CommentOnScore()
   707 	local lGameOver, lTied = CommentOnScore()
   696 
   708 	local bestScore = 0
   697 	-- end game if its at round limit
   709 	local bestClan = -1
   698 	if SI.roundNumber >= SI.roundLimit then
   710 
   699 
   711 	-- Game has been determined to be over, so end it
       
   712 	if lGameOver then
       
   713 
       
   714 		-- Get winning score
   700 		for i = 0, (TeamsCount-1) do
   715 		for i = 0, (TeamsCount-1) do
   701 			if SI.teamScore[i] > SI.bestScore then
   716 			if SI.teamScore[i] > bestScore then
   702 				SI.bestScore = SI.teamScore[i]
   717 				bestScore = SI.teamScore[i]
   703 				SI.bestClan = SI.teamClan[i]
   718 				bestClan = SI.teamClan[i]
   704 			end
   719 			end
   705 		end
   720 		end
   706 
   721 
   707 		-- Kill off all the losers
   722 		-- Kill off all the losers
   708 		for i = 0, (SI.numhhs-1) do
   723 		for i = 0, (SI.numhhs-1) do
   709 			if GetHogClan(SI.hhs[i]) ~= SI.bestClan then
   724 			if GetHogClan(SI.hhs[i]) ~= bestClan then
   710 				SetEffect(SI.hhs[i], heResurrectable, 0)
   725 				SetEffect(SI.hhs[i], heResurrectable, 0)
   711 				SetHealth(SI.hhs[i],0)
   726 				SetHealth(SI.hhs[i],0)
   712 			end
   727 			end
   713 		end
   728 		end
   714 
   729 
   715 		-- Game over
   730 		-- Game over
   716 		SI.gameOver = true
   731 		SI.gameOver = true
   717 		EndTurn(true)
   732 		EndTurn(true)
   718 		SI.TimeLeft = 0
   733 		SI.TimeLeft = 0
   719 		SendStat(siGraphTitle, loc("Score graph"))
   734 		SendStat(siGraphTitle, loc("Score graph"))
       
   735 
       
   736 	-- Round limit passed and teams are tied!
       
   737 	elseif lTied then
       
   738 		-- Enter (or continue) tie-breaking phase...
       
   739 
       
   740 		-- Rules in case of a tie:
       
   741 		-- 1) All teams that are not tied for the lead are killed (they can't play anymore, but they will keep their score and be ranked normally)
       
   742 		-- 2) Another round is played with the remaining teams
       
   743 		-- 3) After this round, scores are checked again to determine a winner. If there's a tie again, this procedure is repeated
       
   744 
       
   745 		-- Get leading teams
       
   746 		for i = 0, (TeamsCount-1) do
       
   747 			if SI.teamScore[i] > bestScore then
       
   748 				bestScore = SI.teamScore[i]
       
   749 			end
       
   750 		end
       
   751 
       
   752 		local tiedForTheLead = {}
       
   753 		for i = 0, (TeamsCount-1) do
       
   754 			if SI.teamScore[i] == bestScore then
       
   755 				tiedForTheLead[i] = true
       
   756 			end
       
   757 		end
       
   758 
       
   759 		local wasCurrent = false
       
   760 		-- Kill teams not in the top
       
   761 		for i = 0, (SI.numhhs-1) do
       
   762 			local hog = SI.hhs[i]
       
   763 			if GetHealth(hog) then -- check if hog is still alive
       
   764 				local team = SI.teamNameArrReverse[GetHogTeamName(hog)]
       
   765 				if team and tiedForTheLead[team] ~= true then
       
   766 					-- hilarious loser face
       
   767 					SetState(hog, bor(GetState(hog), gstLoser))
       
   768 					-- die!
       
   769 					SetEffect(hog, heResurrectable, 0)
       
   770 					SetHealth(hog, 0)
       
   771 					-- Note the death might not trigger immediately since we
       
   772 					-- zero the health at the beginning of a turn rather than
       
   773 					-- the end of one.
       
   774 					-- It's just a minor visual thing, not a big deal.
       
   775 					if hog == CurrentHedgehog then
       
   776 						wasCurrent = true
       
   777 					end
       
   778 				end
       
   779 			end
       
   780 		end
       
   781 
       
   782 		-- if current hedgehog was among the loser, end the turn
       
   783 		if wasCurrent then
       
   784 			EndTurn(true)
       
   785 		end
       
   786 
       
   787 		-- From that point on, the game just continues normally ...
   720 	end
   788 	end
   721 end
   789 end
   722 
   790 
   723 -- gaudy racer
   791 -- gaudy racer
   724 function CheckForNewRound()
   792 function CheckForNewRound()
   725 
   793 
   726 	if GetHogClan(CurrentHedgehog) == SI.firstClan then
   794 	if TotalRounds > 0 and TotalRounds > SI.lastRound then
   727 		onNewRound()
   795 		onNewRound()
   728 	end
   796 	end
   729 
   797 
   730 end
   798 end
   731 
   799 
  1106 
  1174 
  1107 	-- Handle Starting Stage of Game
  1175 	-- Handle Starting Stage of Game
  1108 	if (SI.gameOver == false) and (SI.gameBegun == false) then
  1176 	if (SI.gameOver == false) and (SI.gameBegun == false) then
  1109 		SI.gameBegun = true
  1177 		SI.gameBegun = true
  1110 		SI.roundNumber = 0 -- 0
  1178 		SI.roundNumber = 0 -- 0
  1111 		SI.firstClan = GetHogClan(CurrentHedgehog)
       
  1112 	end
  1179 	end
  1113 
  1180 
  1114 	if SI.gameOver == true then
  1181 	if SI.gameOver == true then
  1115 		SI.stopMovement = true
  1182 		SI.stopMovement = true
  1116 		SI.tumbleStarted = false
  1183 		SI.tumbleStarted = false
  1301 							hogName = GetHogName(CurrentHedgehog),
  1368 							hogName = GetHogName(CurrentHedgehog),
  1302 							teamName = GetHogTeamName(CurrentHedgehog),
  1369 							teamName = GetHogTeamName(CurrentHedgehog),
  1303 							value = SI.shotsHit, 
  1370 							value = SI.shotsHit, 
  1304 						}
  1371 						}
  1305 					end
  1372 					end
  1306 		
  1373 
  1307 				end
  1374 				end
  1308 
  1375 
  1309 				-- other awards
  1376 				-- other awards
  1310 				SI.awardRoundScore = UpdateSimpleAward(SI.awardRoundScore, SI.roundScore, 50)
  1377 				SI.awardRoundScore = UpdateSimpleAward(SI.awardRoundScore, SI.roundScore, 50)
  1311 				SI.awardRoundKills = UpdateSimpleAward(SI.awardRoundKills, SI.roundKills, 5)
  1378 				SI.awardRoundKills = UpdateSimpleAward(SI.awardRoundKills, SI.roundKills, 5)