110 | function LightWildlife:createAnimals(name, spawnPosX, spawnPosY, spawnPosZ, nbAnimals) |
111 | if #self.animals == 0 then |
112 | for i = 1, nbAnimals do |
113 | local node, sharedLoadRequestId = g_i3DManager:loadSharedI3DFile(self.i3dFilename, false, false) |
114 | if node ~= nil then |
115 | link(getRootNode(), node) |
116 | |
117 | local shaderNode = I3DUtil.indexToObject(node, self.shaderNodeString) |
118 | local animal = LightWildlifeAnimal.new(self, i, node, shaderNode) |
119 | |
120 | animal:init(spawnPosX, spawnPosZ, self.randomSpawnRadius, self.animalStates) |
121 | animal.sharedLoadRequestId = sharedLoadRequestId |
122 | table.insert(self.animals, animal) |
123 | end |
124 | end |
125 | |
126 | setWorldTranslation(self.soundsNode, spawnPosX, spawnPosY, spawnPosZ) |
127 | |
128 | return 1 |
129 | end |
130 | return 0 |
131 | end |
211 | function LightWildlife:getClosestDistance(refPosX, refPosY, refPosZ) |
212 | local closestDistSq = nil |
213 | |
214 | for _, animal in pairs(self.animals) do |
215 | if entityExists(animal.i3dNodeId) then |
216 | local x, y, z = getWorldTranslation(animal.i3dNodeId) |
217 | local deltaX = refPosX - x |
218 | local deltaY = refPosY - y |
219 | local deltaZ = refPosZ - z |
220 | local distSq = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ |
221 | |
222 | if closestDistSq == nil or (closestDistSq ~= nil and distSq < closestDistSq) then |
223 | closestDistSq = distSq |
224 | end |
225 | end |
226 | end |
227 | if closestDistSq == nil then |
228 | closestDistSq = 0.0 |
229 | end |
230 | return closestDistSq |
231 | end |
253 | function LightWildlife:getTerrainHeightWithProps(x, z) |
254 | local terrainY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z) |
255 | local offset = 5.0 |
256 | local collisionMask = 63 |
257 | |
258 | self.groundY = -1.0 |
259 | raycastClosest(x, terrainY + offset, z, 0.0, -1.0, 0.0, "groundRaycastCallback", 5.0, self, collisionMask) |
260 | return math.max(terrainY, self.groundY) |
261 | end |
58 | function LightWildlife:load(xmlFilename) |
59 | self.xmlFilename = Utils.getFilename(xmlFilename, self.baseDirectory) |
60 | local xmlFile = loadXMLFile("TempXML", self.xmlFilename) |
61 | if xmlFile == 0 then |
62 | self.xmlFilename = nil |
63 | return false |
64 | end |
65 | |
66 | local key = "wildlifeAnimal" |
67 | if hasXMLProperty(xmlFile, key) then |
68 | self.type = getXMLString(xmlFile, key .. "#type") |
69 | self.randomSpawnRadius = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#randomSpawnRadius"), 0.0) |
70 | local i3dFilename = getXMLString(xmlFile, key .. ".asset#filename") |
71 | self.shaderNodeString = getXMLString(xmlFile, key .. ".animations#shaderNode") |
72 | self.shaderParmId = getXMLString(xmlFile, key .. ".animations#shaderParameterId") |
73 | self.shaderParmOpcode = getXMLString(xmlFile, key .. ".animations#shaderParameterOpcode") |
74 | self.shaderParmSpeed = getXMLString(xmlFile, key .. ".animations#shaderParameterSpeed") |
75 | self.animations = {} |
76 | self.animations["default"] = {name="default", opcode=0, speed=0.0, transitionTimer=0.0} |
77 | |
78 | local i = 0 |
79 | while true do |
80 | local animkey = string.format(key .. ".animations.animation(%d)", i) |
81 | if not hasXMLProperty(xmlFile, animkey) then |
82 | break |
83 | end |
84 | local state = Utils.getNoNil(getXMLString(xmlFile, animkey.."#conditionState"), "") |
85 | local animation = {} |
86 | animation.opcode = Utils.getNoNil(getXMLInt(xmlFile, animkey.."#opcode"), 0) |
87 | animation.speed = Utils.getNoNil(getXMLFloat(xmlFile, animkey.."#speed"), 0.0) |
88 | animation.transitionTimer = Utils.getNoNil(getXMLFloat(xmlFile, animkey.."#transitionTimer"), 1.0) * 1000.0 |
89 | self.animations[state] = animation |
90 | i = i + 1 |
91 | end |
92 | if self.type ~= nil and i3dFilename ~= nil then |
93 | self.i3dFilename = Utils.getFilename(i3dFilename, self.baseDirectory) |
94 | local node, sharedLoadRequestId = g_i3DManager:loadSharedI3DFile(self.i3dFilename, false, false) |
95 | if node ~= 0 then |
96 | delete(node) |
97 | self.cacheLoadRequestId = sharedLoadRequestId |
98 | end |
99 | delete(xmlFile) |
100 | return true |
101 | end |
102 | end |
103 | |
104 | delete(xmlFile) |
105 | return false |
106 | end |
40 | function LightWildlife.new(customMt) |
41 | local self = setmetatable({}, customMt or LightWildlife_mt) |
42 | |
43 | self.type = "" |
44 | self.i3dFilename = nil |
45 | self.sharedLoadRequestId = nil |
46 | self.animals = {} |
47 | self.animalStates = {} |
48 | local defaultState = {id="default", classObject=LightWildlifeStateDefault} |
49 | table.insert(self.animalStates, defaultState) |
50 | self.soundsNode = createTransformGroup("lightWildlifeSounds") |
51 | link(getRootNode(), self.soundsNode) |
52 | |
53 | return self |
54 | end |
171 | function LightWildlife:removeFarAwayAnimals(maxDistance, refPosX, refPosY, refPosZ) |
172 | local removeCount = 0 |
173 | |
174 | for i=#self.animals, 1, -1 do |
175 | local deleteAnimal = false |
176 | local animal = self.animals[i] |
177 | if entityExists(self.animals[i].i3dNodeId) then |
178 | local x, y, z = getWorldTranslation(self.animals[i].i3dNodeId) |
179 | local deltaX = refPosX - x |
180 | local deltaY = refPosY - y |
181 | local deltaZ = refPosZ - z |
182 | local distSq = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ |
183 | |
184 | if distSq > (maxDistance * maxDistance) then |
185 | delete(self.animals[i].i3dNodeId) |
186 | deleteAnimal = true |
187 | end |
188 | else |
189 | deleteAnimal = true |
190 | end |
191 | |
192 | if deleteAnimal then |
193 | table.remove(self.animals, i) |
194 | removeCount = removeCount + 1 |
195 | |
196 | if animal.sharedLoadRequestId ~= nil then |
197 | g_i3DManager:releaseSharedI3DFile(animal.sharedLoadRequestId) |
198 | animal.sharedLoadRequestId = nil |
199 | end |
200 | end |
201 | end |
202 | return removeCount |
203 | end |