1--------------------------------------------------------------------------------
2--------------------------------------------------------------------------------
3--
4--  file:    weapondefs_post.lua
5--  brief:   weaponDef post processing
6--  author:  Dave Rodgers
7--
8--  Copyright (C) 2008.
9--  Licensed under the terms of the GNU GPL, v2 or later.
10--
11--------------------------------------------------------------------------------
12--------------------------------------------------------------------------------
13--
14--  Per-unitDef weaponDefs
15--
16
17local function isbool(x)   return (type(x) == 'boolean') end
18local function istable(x)  return (type(x) == 'table')   end
19local function isnumber(x) return (type(x) == 'number')  end
20local function isstring(x) return (type(x) == 'string')  end
21
22local function tobool(val)
23  local t = type(val)
24  if (t == 'nil') then
25    return false
26  elseif (t == 'boolean') then
27    return val
28  elseif (t == 'number') then
29    return (val ~= 0)
30  elseif (t == 'string') then
31    return ((val ~= '0') and (val ~= 'false'))
32  end
33  return false
34end
35
36local function hs2rgb(h, s)
37	--// FIXME? ignores saturation completely
38	s = 1
39
40	local invSat = 1 - s
41
42	if (h > 0.5) then h = h + 0.1 end
43	if (h > 1.0) then h = h - 1.0 end
44
45	local r = invSat / 2.0
46	local g = invSat / 2.0
47	local b = invSat / 2.0
48
49	if (h < (1.0 / 6.0)) then
50		r = r + s
51		g = g + s * (h * 6.0)
52	elseif (h < (1.0 / 3.0)) then
53		g = g + s
54		r = r + s * ((1.0 / 3.0 - h) * 6.0)
55	elseif (h < (1.0 / 2.0)) then
56		g = g + s
57		b = b + s * ((h - (1.0 / 3.0)) * 6.0)
58	elseif (h < (2.0 / 3.0)) then
59		b = b + s
60		g = g + s * ((2.0 / 3.0 - h) * 6.0)
61	elseif (h < (5.0 / 6.0)) then
62		b = b + s
63		r = r + s * ((h - (2.0 / 3.0)) * 6.0)
64	else
65		r = r + s
66		b = b + s * ((3.0 / 3.0 - h) * 6.0)
67	end
68
69	return ("%0.3f %0.3f %0.3f"):format(r,g,b)
70end
71
72--------------------------------------------------------------------------------
73
74local function BackwardCompability(wdName, wd)
75  -- weapon reloadTime and stockpileTime were seperated in 77b1
76  if (tobool(wd.stockpile) and (wd.stockpiletime==nil)) then
77    wd.stockpiletime = wd.reloadtime
78    wd.reloadtime    = 2             -- 2 seconds
79  end
80
81  -- auto detect ota weapontypes
82  if (wd.weapontype == nil) then
83    local rendertype = tonumber(wd.rendertype) or 0
84
85    if (tobool(wd.dropped)) then
86      wd.weapontype = "AircraftBomb"
87    elseif (tobool(wd.vlaunch)) then
88      wd.weapontype = "StarburstLauncher"
89    elseif (tobool(wd.beamlaser)) then
90      wd.weapontype = "BeamLaser"
91    elseif (tobool(wd.isshield)) then
92      wd.weapontype = "Shield"
93    elseif (tobool(wd.waterweapon)) then
94      wd.weapontype = "TorpedoLauncher"
95    elseif (wdName:lower():find("disintegrator",1,true)) then
96      wd.weaponType = "DGun"
97    elseif (tobool(wd.lineofsight)) then
98      if (rendertype == 7) then
99        wd.weapontype = "LightningCannon"
100
101      -- swta fix (outdated?)
102      elseif (wd.model and wd.model:lower():find("laser",1,true)) then
103        wd.weapontype = "LaserCannon"
104
105      elseif (tobool(wd.beamweapon)) then
106        wd.weapontype = "LaserCannon"
107      elseif (tobool(wd.smoketrail)) then
108        wd.weapontype = "MissileLauncher"
109      elseif (rendertype == 4 and tonumber(wd.color)==2) then
110        wd.weapontype = "EmgCannon"
111      elseif (rendertype == 5) then
112        wd.weapontype = "Flame"
113      --elseif(rendertype == 1) then
114      --  wd.weapontype = "MissileLauncher"
115      else
116        wd.weapontype = "Cannon"
117      end
118    else
119      wd.weapontype = "Cannon"
120    end
121  end
122
123  if (wd.weapontype == "LightingCannon") then
124    wd.weapontype = "LightningCannon"
125  elseif (wd.weapontype == "AircraftBomb") then
126    if (wd.manualbombsettings) then
127      wd.reloadtime = tonumber(wd.reloadtime or 1.0)
128      wd.burstrate  = tonumber(wd.burstrate or 0.1)
129
130      if (wd.reloadtime < 0.5) then
131        wd.burstrate  = math.min(0.2, wd.reloadtime)         -- salvodelay
132        wd.burst      = math.floor((1.0 / wd.burstrate) + 1) -- salvosize
133        wd.reloadtime = 5.0
134      else
135        wd.burstrate = math.min(0.4, wd.reloadtime)
136        wd.burst     = 2
137      end
138    end
139  end
140
141  if (not wd.rgbcolor) then
142    if (wd.weapontype == "Cannon") then
143      wd.rgbcolor = "1.0 0.5 0.0"
144    elseif (wd.weapontype == "EmgCannon") then
145      wd.rgbcolor = "0.9 0.9 0.2"
146    else
147      local hue = (wd.color or 0) / 255
148      local sat = (wd.color2 or 0) / 255
149      wd.rgbcolor = hs2rgb(hue, sat)
150    end
151  end
152
153  if (not wd.craterareaofeffect) then
154    wd.craterareaofeffect = tonumber(wd.areaofeffect or 0) * 1.5
155  end
156
157  if (tobool(wd.ballistic) or tobool(wd.dropped)) then
158    wd.gravityaffected = true
159  end
160end
161
162--------------------------------------------------------------------------------
163
164local function ProcessUnitDef(udName, ud)
165
166  local wds = ud.weapondefs
167  if (not istable(wds)) then
168    return
169  end
170
171  -- add this unitDef's weaponDefs
172  for wdName, wd in pairs(wds) do
173    if (isstring(wdName) and istable(wd)) then
174      local fullName = udName .. '_' .. wdName
175      WeaponDefs[fullName] = wd
176    end
177  end
178
179  -- convert the weapon names
180  local weapons = ud.weapons
181  if (istable(weapons)) then
182    for i = 1, 32 do
183      local w = weapons[i]
184      if (istable(w)) then
185        if (isstring(w.def)) then
186          local ldef = string.lower(w.def)
187          local fullName = udName .. '_' .. ldef
188          local wd = WeaponDefs[fullName]
189          if (istable(wd)) then
190            w.name = fullName
191          end
192        end
193        w.def = nil
194      end
195    end
196  end
197
198  -- convert the death explosions
199  if (isstring(ud.explodeas)) then
200    local fullName = udName .. '_' .. ud.explodeas
201    if (WeaponDefs[fullName]) then
202      ud.explodeas = fullName
203    end
204  end
205  if (isstring(ud.selfdestructas)) then
206    local fullName = udName .. '_' .. ud.selfdestructas
207    if (WeaponDefs[fullName]) then
208      ud.selfdestructas = fullName
209    end
210  end
211end
212
213--------------------------------------------------------------------------------
214
215local function ProcessWeaponDef(wdName, wd)
216
217  -- backward compability
218  BackwardCompability(wdName, wd)
219end
220
221--------------------------------------------------------------------------------
222
223-- Process the unitDefs
224local UnitDefs = DEFS.unitDefs
225
226for udName, ud in pairs(UnitDefs) do
227  if (isstring(udName) and istable(ud)) then
228    ProcessUnitDef(udName, ud)
229  end
230end
231
232
233for wdName, wd in pairs(WeaponDefs) do
234  if (isstring(wdName) and istable(wd)) then
235    ProcessWeaponDef(wdName, wd)
236  end
237end
238
239
240--------------------------------------------------------------------------------
241--------------------------------------------------------------------------------
242