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 #include "object/implementation/task_executor_impl.h"
21
22 #include "object/object.h"
23 #include "object/old_object.h"
24
25 #include "object/task/taskadvance.h"
26 #include "object/task/taskbuild.h"
27 #include "object/task/taskdeletemark.h"
28 #include "object/task/taskfire.h"
29 #include "object/task/taskfireant.h"
30 #include "object/task/taskgungoal.h"
31 #include "object/task/taskinfo.h"
32 #include "object/task/taskpen.h"
33 #include "object/task/taskrecover.h"
34 #include "object/task/tasksearch.h"
35 #include "object/task/taskspiderexplo.h"
36 #include "object/task/tasktake.h"
37 #include "object/task/taskterraform.h"
38 #include "object/task/taskturn.h"
39 #include "object/task/taskwait.h"
40
CTaskExecutorObjectImpl(ObjectInterfaceTypes & types,CObject * object)41 CTaskExecutorObjectImpl::CTaskExecutorObjectImpl(ObjectInterfaceTypes& types, CObject* object)
42 : CTaskExecutorObject(types)
43 , m_object(object)
44 {}
45
~CTaskExecutorObjectImpl()46 CTaskExecutorObjectImpl::~CTaskExecutorObjectImpl()
47 {}
48
EventProcess(const Event & event)49 bool CTaskExecutorObjectImpl::EventProcess(const Event &event)
50 {
51 // NOTE: This function CAN'T BE CALLED BETWEEN CTask::EventProcess AND CScriptFunctions::Process, otherwise weird stuff may happen to scripts (they'll be stuck executing the same task over and over again)
52 EndedTask();
53
54 if ( m_foregroundTask != nullptr )
55 {
56 m_foregroundTask->EventProcess(event);
57 }
58
59 if ( m_backgroundTask != nullptr )
60 {
61 m_backgroundTask->EventProcess(event);
62 }
63
64 return true;
65 }
66
IsForegroundTask()67 bool CTaskExecutorObjectImpl::IsForegroundTask()
68 {
69 return m_foregroundTask != nullptr;
70 }
71
IsBackgroundTask()72 bool CTaskExecutorObjectImpl::IsBackgroundTask()
73 {
74 return m_backgroundTask != nullptr;
75 }
76
GetForegroundTask()77 CForegroundTask* CTaskExecutorObjectImpl::GetForegroundTask()
78 {
79 return m_foregroundTask.get();
80 }
81
GetBackgroundTask()82 CBackgroundTask* CTaskExecutorObjectImpl::GetBackgroundTask()
83 {
84 return m_backgroundTask.get();
85 }
86
87 // Stops the current task.
88
StopForegroundTask()89 void CTaskExecutorObjectImpl::StopForegroundTask()
90 {
91 if (m_foregroundTask != nullptr)
92 {
93 m_foregroundTask->Abort();
94 m_foregroundTask.reset();
95 }
96 }
97
98 // Stops the current secondary task.
99
StopBackgroundTask()100 void CTaskExecutorObjectImpl::StopBackgroundTask()
101 {
102 if (m_backgroundTask != nullptr)
103 {
104 m_backgroundTask->Abort();
105 m_backgroundTask.reset();
106 }
107 }
108
109 // Completes the task when the time came.
110
EndedTask()111 Error CTaskExecutorObjectImpl::EndedTask()
112 {
113 if (m_backgroundTask != nullptr) // current task?
114 {
115 Error err = m_backgroundTask->IsEnded();
116 if ( err != ERR_CONTINUE ) // job ended?
117 {
118 m_backgroundTask.reset();
119 m_object->UpdateInterface();
120 }
121 }
122
123 if (m_foregroundTask != nullptr) // current task?
124 {
125 Error err = m_foregroundTask->IsEnded();
126 if ( err != ERR_CONTINUE ) // job ended?
127 {
128 m_foregroundTask.reset();
129 m_object->UpdateInterface();
130 }
131 return err;
132 }
133
134 return ERR_STOP;
135 }
136
137 template<typename TaskType, typename... Args>
StartForegroundTask(Args &&...args)138 Error CTaskExecutorObjectImpl::StartForegroundTask(Args&&... args)
139 {
140 static_assert(std::is_base_of<CForegroundTask, TaskType>::value, "not a foreground task");
141
142 StopForegroundTask();
143
144 assert(m_object->Implements(ObjectInterfaceType::Old)); //TODO
145 std::unique_ptr<TaskType> task = MakeUnique<TaskType>(dynamic_cast<COldObject*>(m_object));
146 Error err = task->Start(std::forward<Args>(args)...);
147 if (err == ERR_OK)
148 m_foregroundTask = std::move(task);
149 m_object->UpdateInterface();
150 return err;
151 }
152
153 template<typename TaskType, typename... Args>
StartBackgroundTask(Args &&...args)154 Error CTaskExecutorObjectImpl::StartBackgroundTask(Args&&... args)
155 {
156 static_assert(std::is_base_of<CBackgroundTask, TaskType>::value, "not a background task");
157
158 Error err;
159 TaskType* task = dynamic_cast<TaskType*>(m_backgroundTask.get());
160 if (task != nullptr)
161 {
162 err = task->Start(std::forward<Args>(args)...);
163 if (err != ERR_OK)
164 m_backgroundTask.reset();
165 }
166 else
167 {
168 m_backgroundTask.reset(); // In case the old task was of a different type
169
170 assert(m_object->Implements(ObjectInterfaceType::Old)); //TODO
171 std::unique_ptr<TaskType> newTask = MakeUnique<TaskType>(dynamic_cast<COldObject*>(m_object));
172 err = newTask->Start(std::forward<Args>(args)...);
173 if (err == ERR_OK)
174 m_backgroundTask = std::move(newTask);
175 }
176 m_object->UpdateInterface();
177 return err;
178 }
179
StartTaskTake()180 Error CTaskExecutorObjectImpl::StartTaskTake()
181 {
182 return StartForegroundTask<CTaskTake>();
183 }
184
StartTaskManip(TaskManipOrder order,TaskManipArm arm)185 Error CTaskExecutorObjectImpl::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
186 {
187 return StartForegroundTask<CTaskManip>(order, arm);
188 }
189
StartTaskFlag(TaskFlagOrder order,int rank)190 Error CTaskExecutorObjectImpl::StartTaskFlag(TaskFlagOrder order, int rank)
191 {
192 return StartForegroundTask<CTaskFlag>(order, rank);
193 }
194
StartTaskBuild(ObjectType type)195 Error CTaskExecutorObjectImpl::StartTaskBuild(ObjectType type)
196 {
197 return StartForegroundTask<CTaskBuild>(type);
198 }
199
StartTaskSearch()200 Error CTaskExecutorObjectImpl::StartTaskSearch()
201 {
202 return StartForegroundTask<CTaskSearch>();
203 }
204
StartTaskDeleteMark()205 Error CTaskExecutorObjectImpl::StartTaskDeleteMark()
206 {
207 return StartForegroundTask<CTaskDeleteMark>();
208 }
209
StartTaskTerraform()210 Error CTaskExecutorObjectImpl::StartTaskTerraform()
211 {
212 return StartForegroundTask<CTaskTerraform>();
213 }
214
StartTaskRecover()215 Error CTaskExecutorObjectImpl::StartTaskRecover()
216 {
217 return StartForegroundTask<CTaskRecover>();
218 }
219
StartTaskFire(float delay)220 Error CTaskExecutorObjectImpl::StartTaskFire(float delay)
221 {
222 return StartForegroundTask<CTaskFire>(delay);
223 }
224
StartTaskFireAnt(Math::Vector impact)225 Error CTaskExecutorObjectImpl::StartTaskFireAnt(Math::Vector impact)
226 {
227 return StartForegroundTask<CTaskFireAnt>(impact);
228 }
229
StartTaskSpiderExplo()230 Error CTaskExecutorObjectImpl::StartTaskSpiderExplo()
231 {
232 return StartForegroundTask<CTaskSpiderExplo>();
233 }
234
StartTaskPen(bool down,TraceColor color)235 Error CTaskExecutorObjectImpl::StartTaskPen(bool down, TraceColor color)
236 {
237 return StartForegroundTask<CTaskPen>(down, color);
238 }
239
240
StartTaskWait(float time)241 Error CTaskExecutorObjectImpl::StartTaskWait(float time)
242 {
243 return StartForegroundTask<CTaskWait>(time);
244 }
245
StartTaskAdvance(float length)246 Error CTaskExecutorObjectImpl::StartTaskAdvance(float length)
247 {
248 return StartForegroundTask<CTaskAdvance>(length);
249 }
250
StartTaskTurn(float angle)251 Error CTaskExecutorObjectImpl::StartTaskTurn(float angle)
252 {
253 return StartForegroundTask<CTaskTurn>(angle);
254 }
255
StartTaskGoto(Math::Vector pos,float altitude,TaskGotoGoal goalMode,TaskGotoCrash crashMode)256 Error CTaskExecutorObjectImpl::StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode)
257 {
258 return StartForegroundTask<CTaskGoto>(pos, altitude, goalMode, crashMode);
259 }
260
StartTaskInfo(const char * name,float value,float power,bool bSend)261 Error CTaskExecutorObjectImpl::StartTaskInfo(const char *name, float value, float power, bool bSend)
262 {
263 return StartForegroundTask<CTaskInfo>(name, value, power, bSend);
264 }
265
266
StartTaskShield(TaskShieldMode mode,float delay)267 Error CTaskExecutorObjectImpl::StartTaskShield(TaskShieldMode mode, float delay)
268 {
269 return StartBackgroundTask<CTaskShield>(mode, delay);
270 }
271
StartTaskGunGoal(float dirV,float dirH)272 Error CTaskExecutorObjectImpl::StartTaskGunGoal(float dirV, float dirH)
273 {
274 return StartBackgroundTask<CTaskGunGoal>(dirV, dirH);
275 }
276