1 /*
2 * This file is part of the Colobot: Gold Edition source code
3 * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4 * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see http://gnu.org/licenses
18 */
19
20
21 #include "object/auto/automush.h"
22
23 #include "common/make_unique.h"
24
25 #include "level/parser/parserline.h"
26 #include "level/parser/parserparam.h"
27
28 #include "object/object_manager.h"
29 #include "object/old_object.h"
30
31 #include "sound/sound.h"
32
33
34 // Object's constructor.
35
CAutoMush(COldObject * object)36 CAutoMush::CAutoMush(COldObject* object) : CAuto(object)
37 {
38 Init();
39 }
40
41 // Object's destructor.
42
~CAutoMush()43 CAutoMush::~CAutoMush()
44 {
45 }
46
47
48 // Destroys the object.
49
DeleteObject(bool bAll)50 void CAutoMush::DeleteObject(bool bAll)
51 {
52 CAuto::DeleteObject(bAll);
53 }
54
55
56 // Initialize the object.
57
Init()58 void CAutoMush::Init()
59 {
60 m_phase = AMP_WAIT;
61 m_progress = 0.0f;
62 m_speed = 1.0f/4.0f;
63
64 m_time = 0.0f;
65 m_lastParticle = 0.0f;
66 }
67
68
69 // Management of an event.
70
EventProcess(const Event & event)71 bool CAutoMush::EventProcess(const Event &event)
72 {
73 Math::Vector pos, speed, dir;
74 Math::Point dim;
75 float factor, zoom, size, angle;
76 int i, channel;
77
78 CAuto::EventProcess(event);
79
80 if ( m_engine->GetPause() ) return true;
81 if ( event.type != EVENT_FRAME ) return true;
82
83 m_progress += event.rTime*m_speed;
84
85 factor = 0.0f;
86 size = 1.0f;
87
88 if ( m_phase == AMP_WAIT )
89 {
90 if ( m_progress >= 1.0f )
91 {
92 if ( !SearchTarget() )
93 {
94 m_phase = AMP_WAIT;
95 m_progress = 0.0f;
96 m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
97 }
98 else
99 {
100 m_phase = AMP_SNIF;
101 m_progress = 0.0f;
102 m_speed = 1.0f/1.5f;
103 }
104 }
105 }
106
107 if ( m_phase == AMP_SNIF )
108 {
109 if ( m_progress < 1.0f )
110 {
111 factor = m_progress;
112 }
113 else
114 {
115 m_phase = AMP_ZOOM;
116 m_progress = 0.0f;
117 m_speed = 1.0f/1.0f;
118 }
119 }
120
121 if ( m_phase == AMP_ZOOM )
122 {
123 if ( m_progress < 1.0f )
124 {
125 factor = 1.0f;
126 size = 1.0f+m_progress*0.3f;
127 }
128 else
129 {
130 m_sound->Play(SOUND_MUSHROOM, m_object->GetPosition());
131
132 m_phase = AMP_FIRE;
133 m_progress = 0.0f;
134 m_speed = 1.0f/1.0f;
135 }
136 }
137
138 if ( m_phase == AMP_FIRE )
139 {
140 if ( m_progress < 1.0f )
141 {
142 factor = 1.0f-m_progress;
143 size = 1.0f+(1.0f-m_progress)*0.3f;
144
145 if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
146 {
147 m_lastParticle = m_time;
148
149 for ( i=0 ; i<10 ; i++ )
150 {
151 pos = m_object->GetPosition();
152 pos.y += 5.0f;
153 speed.x = (Math::Rand()-0.5f)*200.0f;
154 speed.z = (Math::Rand()-0.5f)*200.0f;
155 speed.y = -(20.0f+Math::Rand()*20.0f);
156 dim.x = 1.0f;
157 dim.y = dim.x;
158 channel = m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIGUN2, 2.0f, 100.0f, 0.0f);
159 m_particle->SetObjectFather(channel, m_object);
160 }
161 }
162 }
163 else
164 {
165 m_phase = AMP_SMOKE;
166 m_progress = 0.0f;
167 m_speed = 1.0f/2.0f;
168 }
169 }
170
171 if ( m_phase == AMP_SMOKE )
172 {
173 if ( m_progress < 1.0f )
174 {
175 if ( m_lastParticle+m_engine->ParticleAdapt(0.10f) <= m_time )
176 {
177 m_lastParticle = m_time;
178
179 pos = m_object->GetPosition();
180 pos.y += 5.0f;
181 speed.x = (Math::Rand()-0.5f)*4.0f;
182 speed.z = (Math::Rand()-0.5f)*4.0f;
183 speed.y = -(0.5f+Math::Rand()*0.5f);
184 dim.x = Math::Rand()*2.5f+2.0f;
185 dim.y = dim.x;
186 m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISMOKE3, 4.0f, 0.0f, 0.0f);
187 }
188 }
189 else
190 {
191 m_phase = AMP_WAIT;
192 m_progress = 0.0f;
193 m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
194 }
195 }
196
197 if ( factor != 0.0f || size != 1.0f )
198 {
199 dir.x = sinf(m_time*Math::PI*4.0f);
200 dir.z = cosf(m_time*Math::PI*4.0f);
201
202 angle = sinf(m_time*10.0f)*factor*0.04f;
203 m_object->SetRotationX(angle*dir.z);
204 m_object->SetRotationZ(angle*dir.x);
205
206 zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f;
207 m_object->SetScaleX(zoom*size);
208 zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f;
209 m_object->SetScaleY(zoom*size);
210 zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f;
211 m_object->SetScaleZ(zoom*size);
212 }
213 else
214 {
215 m_object->SetRotationX(0.0f);
216 m_object->SetRotationZ(0.0f);
217 m_object->SetScale(Math::Vector(1.0f, 1.0f, 1.0f));
218 }
219
220 return true;
221 }
222
223
224 // Seeking a nearby target.
225
SearchTarget()226 bool CAutoMush::SearchTarget()
227 {
228 Math::Vector iPos = m_object->GetPosition();
229
230 for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects())
231 {
232 if ( obj->GetLock() ) continue;
233
234 ObjectType type = obj->GetType();
235 if ( type != OBJECT_MOBILEfa &&
236 type != OBJECT_MOBILEta &&
237 type != OBJECT_MOBILEwa &&
238 type != OBJECT_MOBILEia &&
239 type != OBJECT_MOBILEfb &&
240 type != OBJECT_MOBILEtb &&
241 type != OBJECT_MOBILEwb &&
242 type != OBJECT_MOBILEib &&
243 type != OBJECT_MOBILEfc &&
244 type != OBJECT_MOBILEtc &&
245 type != OBJECT_MOBILEwc &&
246 type != OBJECT_MOBILEic &&
247 type != OBJECT_MOBILEfi &&
248 type != OBJECT_MOBILEti &&
249 type != OBJECT_MOBILEwi &&
250 type != OBJECT_MOBILEii &&
251 type != OBJECT_MOBILEfs &&
252 type != OBJECT_MOBILEts &&
253 type != OBJECT_MOBILEws &&
254 type != OBJECT_MOBILEis &&
255 type != OBJECT_MOBILErt &&
256 type != OBJECT_MOBILErc &&
257 type != OBJECT_MOBILErr &&
258 type != OBJECT_MOBILErs &&
259 type != OBJECT_MOBILEsa &&
260 type != OBJECT_MOBILEtg &&
261 type != OBJECT_MOBILEft &&
262 type != OBJECT_MOBILEtt &&
263 type != OBJECT_MOBILEwt &&
264 type != OBJECT_MOBILEit &&
265 type != OBJECT_MOBILErp &&
266 type != OBJECT_MOBILEst &&
267 type != OBJECT_MOBILEdr &&
268 type != OBJECT_DERRICK &&
269 type != OBJECT_STATION &&
270 type != OBJECT_FACTORY &&
271 type != OBJECT_REPAIR &&
272 type != OBJECT_DESTROYER&&
273 type != OBJECT_CONVERT &&
274 type != OBJECT_TOWER &&
275 type != OBJECT_RESEARCH &&
276 type != OBJECT_RADAR &&
277 type != OBJECT_INFO &&
278 type != OBJECT_ENERGY &&
279 type != OBJECT_LABO &&
280 type != OBJECT_NUCLEAR &&
281 type != OBJECT_PARA &&
282 type != OBJECT_HUMAN ) continue;
283
284 Math::Vector oPos = obj->GetPosition();
285 float dist = Math::Distance(oPos, iPos);
286 if ( dist < 50.0f ) return true;
287 }
288
289 return false;
290 }
291
292
293 // Returns an error due the state of the automation.
294
GetError()295 Error CAutoMush::GetError()
296 {
297 return ERR_OK;
298 }
299
300
301 // Saves all parameters of the controller.
302
Write(CLevelParserLine * line)303 bool CAutoMush::Write(CLevelParserLine* line)
304 {
305 if ( m_phase == AMP_WAIT ) return false;
306
307 line->AddParam("aExist", MakeUnique<CLevelParserParam>(true));
308 CAuto::Write(line);
309 line->AddParam("aPhase", MakeUnique<CLevelParserParam>(static_cast<int>(m_phase)));
310 line->AddParam("aProgress", MakeUnique<CLevelParserParam>(m_progress));
311 line->AddParam("aSpeed", MakeUnique<CLevelParserParam>(m_speed));
312
313 return true;
314 }
315
316 // Restores all parameters of the controller.
317
Read(CLevelParserLine * line)318 bool CAutoMush::Read(CLevelParserLine* line)
319 {
320 if ( !line->GetParam("aExist")->AsBool(false) ) return false;
321
322 CAuto::Read(line);
323 m_phase = static_cast< AutoMushPhase >(line->GetParam("aPhase")->AsInt(AMP_WAIT));
324 m_progress = line->GetParam("aProgress")->AsFloat(0.0f);
325 m_speed = line->GetParam("aSpeed")->AsFloat(1.0f);
326
327 m_lastParticle = 0.0f;
328
329 return true;
330 }
331