File size: 6,123 Bytes
b6a38d7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
MapVar("g_UnitEnemies", {})
MapVar("g_UnitAllEnemies", {})
MapVar("g_UnitAllies", {})
function SideIsAlly(side1, side2)
if side1 == "ally" then side1 = "player1" end
if side2 == "ally" then side2 = "player1" end
if side1 == "enemyNeutral" then side1 = "enemy1" end
if side2 == "enemyNeutral" then side2 = "enemy1" end
return side1 == side2
end
function SideIsEnemy(side1, side2)
if side1 == "enemyNeutral" and not GameState.Conflict then side1 = "neutral" end
if side2 == "enemyNeutral" and not GameState.Conflict then side2 = "neutral" end
return side1 ~= "neutral" and side2 ~= "neutral" and not SideIsAlly(side1, side2)
end
function IsPlayerEnemy(unit)
return unit.team and SideIsEnemy("player1", unit.team.side)
end
local dirty_relations = false --heh
function RecalcDiplomacy()
dirty_relations = false
local unit_Enemies = {}
local unit_AllEnemies = {}
local unit_Allies = {}
for idx1, team in ipairs(g_Teams) do
local team_units = team.units
if #team_units > 0 then
local team_visibility = g_Visibility[team]
local team_enemy_mask = team.enemy_mask
local team_ally_mask = team.ally_mask
for idx2, team2 in ipairs(g_Teams) do
local team2_units = team2.units
if #team2_units > 0 then
if band(team_enemy_mask, team2.team_mask) ~= 0 then
-- all the units of the team have the same enemies. we provide them the same tables
local all_enemies = unit_AllEnemies[team_units[1]]
if all_enemies then
table.iappend(all_enemies, team2_units)
else
all_enemies = table.icopy(team2_units)
for i, unit in ipairs(team_units) do
unit_AllEnemies[unit] = all_enemies
end
end
if team_visibility and #team_visibility > 0 then
for i, unit in ipairs(team_units) do
if unit:IsAware() then
local enemies = unit_Enemies[unit]
for j, other in ipairs(team2_units) do
if team_visibility[other] then
enemies = enemies or {}
table.insert(enemies, other)
end
end
if enemies and not unit_Enemies[unit] then
unit_Enemies[unit] = enemies
for j = i + 1, #team_units do
local unit2 = team_units[j]
if unit2:IsAware() then
unit_Enemies[unit2] = enemies
end
end
end
break
end
end
end
elseif band(team_ally_mask, team2.team_mask) ~= 0 then
for i, unit in ipairs(team_units) do
local allies = unit_Allies[unit]
local start_idx = 0
if allies then
start_idx = #allies
table.iappend(allies, team2_units)
else
allies = table.icopy(team2_units)
unit_Allies[unit] = allies
end
if team == team2 then
table.remove(allies, start_idx + i) -- remove unit
end
end
end
end
end
end
end
g_UnitEnemies = unit_Enemies
g_UnitAllEnemies = unit_AllEnemies
g_UnitAllies = unit_Allies
Msg("UnitRelationsUpdated")
end
function InvalidateDiplomacy()
NetUpdateHash("InvalidateDiplomacy")
dirty_relations = true
if g_Combat then
g_Combat.visibility_update_hash = false
end
Msg("DiplomacyInvalidated")
end
MapVar("g_Diplomacy", {})
local function OnGetRelations()
if dirty_relations then
RecalcDiplomacy()
end
end
function GetEnemies(unit)
OnGetRelations()
return g_UnitEnemies[unit] or empty_table
end
function GetAllEnemyUnits(unit)
OnGetRelations()
return g_UnitAllEnemies[unit] or empty_table
end
function GetAllAlliedUnits(unit)
OnGetRelations()
return g_UnitAllies[unit] or empty_table
end
function GetNearestEnemy(unit, ignore_awareness)
local enemies = ignore_awareness and GetAllEnemyUnits(unit) or GetEnemies(unit)
local nearest
for _, enemy in ipairs(enemies) do
if not nearest or IsCloser(unit, enemy, nearest) then
nearest = enemy
end
end
if nearest then
return nearest, unit:GetDist(nearest)
end
end
function UpdateTeamDiplomacy()
for i, team in ipairs(g_Teams) do
team.team_mask = shift(1, i)
end
local player_side = NetPlayerSide()
for _, team in ipairs(g_Teams) do
team.ally_mask = team.team_mask
team.enemy_mask = 0
for _, other in ipairs(g_Teams) do
if other ~= team then
if SideIsAlly(team.side, other.side) then
team.ally_mask = bor(team.ally_mask, other.team_mask)
end
if SideIsEnemy(team.side, other.side) then
team.enemy_mask = bor(team.enemy_mask, other.team_mask)
end
end
end
if Game and Game.game_type == "HotSeat" then
team.player_team = (team.side == "player1") or (team.side == "player2")
team.player_ally = SideIsAlly("player1", team.side) or SideIsAlly("player2", team.side)
else
team.player_team = team.side == player_side
team.player_ally = SideIsAlly(player_side, team.side)
end
team.player_enemy = SideIsEnemy(player_side, team.side)
team.neutral = team.side == "neutral"
end
InvalidateDiplomacy()
ObjModified(Selection)
end
OnMsg.ConflictStart = UpdateTeamDiplomacy
OnMsg.ConflictEnd = UpdateTeamDiplomacy
OnMsg.CombatStart = function() NetUpdateHash("CombatStart"); InvalidateDiplomacy() end
OnMsg.UnitSideChanged = function() NetUpdateHash("UnitSideChanged"); InvalidateDiplomacy() end
OnMsg.UnitDied = function() NetUpdateHash("UnitDied"); InvalidateDiplomacy() end
OnMsg.UnitDespawned = function(unit)
NetUpdateHash("UnitDespawned");
InvalidateDiplomacy()
end
OnMsg.VillainDefeated = function() NetUpdateHash("VillainDefeated"); InvalidateDiplomacy() end
OnMsg.UnitAwarenessChanged = function() NetUpdateHash("UnitAwarenessChanged"); InvalidateDiplomacy() end
OnMsg.UnitStealthChanged = function() NetUpdateHash("UnitStealthChanged"); InvalidateDiplomacy() end
function NetSyncEvents.UpdateTeamDiplomacy()
UpdateTeamDiplomacy()
end
function NetSyncEvents.InvalidateDiplomacy()
InvalidateDiplomacy()
end
function OnMsg.TeamsUpdated()
if IsRealTimeThread() then
DelayedCall(0, FireNetSyncEventOnHost, "UpdateTeamDiplomacy")
else
UpdateTeamDiplomacy()
end
end
function OnMsg.EnterSector(game_start, load_game)
FireNetSyncEventOnHost("InvalidateDiplomacy")
end |