00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "PathfinderProcess.h"
00021
00022 #include "Actor.h"
00023 #include "Pathfinder.h"
00024 #include "getObject.h"
00025
00026 #include "IDataSource.h"
00027 #include "ODataSource.h"
00028
00029 static const unsigned int PATH_OK = 1;
00030 static const unsigned int PATH_FAILED = 0;
00031
00032
00033 DEFINE_RUNTIME_CLASSTYPE_CODE(PathfinderProcess,Process);
00034
00035 PathfinderProcess::PathfinderProcess() : Process()
00036 {
00037
00038 }
00039
00040 PathfinderProcess::PathfinderProcess(Actor* actor_, ObjId item_, bool hit)
00041 {
00042 assert(actor_);
00043 item_num = actor_->getObjId();
00044 type = 0x0204;
00045
00046
00047 Item* item = getItem(item_);
00048 if (!item) {
00049 perr << "PathfinderProcess: non-existent target" << std::endl;
00050
00051 result = PATH_FAILED;
00052 terminateDeferred();
00053 return;
00054 }
00055
00056 currentstep = 0;
00057 targetitem = item_;
00058 hitmode = hit;
00059 assert(targetitem);
00060
00061 item->getLocation(targetx, targety, targetz);
00062
00063 Pathfinder pf;
00064 pf.init(actor_);
00065 pf.setTarget(item, hit);
00066
00067 bool ok = pf.pathfind(path);
00068
00069 if (!ok) {
00070 perr << "PathfinderProcess: actor " << item_num
00071 << " failed to find path" << std::endl;
00072
00073 result = PATH_FAILED;
00074 terminateDeferred();
00075 return;
00076 }
00077
00078
00079 actor_->setActorFlag(Actor::ACT_PATHFINDING);
00080 }
00081
00082 PathfinderProcess::PathfinderProcess(Actor* actor_,
00083 sint32 x, sint32 y, sint32 z)
00084 {
00085 assert(actor_);
00086 item_num = actor_->getObjId();
00087
00088 targetx = x;
00089 targety = y;
00090 targetz = z;
00091 targetitem = 0;
00092
00093 currentstep = 0;
00094
00095 Pathfinder pf;
00096 pf.init(actor_);
00097 pf.setTarget(targetx, targety, targetz);
00098
00099 bool ok = pf.pathfind(path);
00100
00101 if (!ok) {
00102 perr << "PathfinderProcess: actor " << item_num
00103 << " failed to find path" << std::endl;
00104
00105 result = PATH_FAILED;
00106 terminateDeferred();
00107 return;
00108 }
00109
00110
00111 actor_->setActorFlag(Actor::ACT_PATHFINDING);
00112 }
00113
00114 PathfinderProcess::~PathfinderProcess()
00115 {
00116
00117 }
00118
00119 void PathfinderProcess::terminate()
00120 {
00121 Actor* actor = getActor(item_num);
00122 if (actor) {
00123
00124
00125 actor->clearActorFlag(Actor::ACT_PATHFINDING);
00126 }
00127
00128 Process::terminate();
00129 }
00130
00131 bool PathfinderProcess::run(const uint32 )
00132 {
00133 Actor* actor = getActor(item_num);
00134 assert(actor);
00135
00136 if (!(actor->getFlags() & Item::FLG_FASTAREA)) return false;
00137
00138
00139 bool ok = true;
00140
00141 if (targetitem) {
00142 sint32 curx,cury,curz;
00143 Item* item = getItem(targetitem);
00144 if (!item) {
00145 perr << "PathfinderProcess: target missing" << std::endl;
00146 result = PATH_FAILED;
00147 terminate();
00148 return false;
00149 }
00150
00151 item->getLocation(curx, cury, curz);
00152 if (abs(curx - targetx) >= 32 || abs(cury - targety) >= 32 ||
00153 abs(curz - targetz) >= 8)
00154 {
00155
00156 ok = false;
00157 }
00158 }
00159
00160 if (ok && currentstep >= path.size()) {
00161
00162 #if 0
00163 pout << "PathfinderProcess: done" << std::endl;
00164 #endif
00165 result = PATH_OK;
00166 terminate();
00167 return false;
00168 }
00169
00170
00171
00172 #if 0
00173 pout << "PathfinderProcess: trying step" << std::endl;
00174 #endif
00175
00176
00177
00178
00179
00180 if (actor->getActorFlags() & Actor::ACT_ANIMLOCK) {
00181 perr << "PathfinderProcess: ANIMLOCK, waiting" << std::endl;
00182 return false;
00183 }
00184
00185 if (ok) {
00186 ok = actor->tryAnim(path[currentstep].action,
00187 path[currentstep].direction,
00188 path[currentstep].steps) == Animation::SUCCESS;
00189 }
00190
00191 if (!ok) {
00192 #if 0
00193 pout << "PathfinderProcess: recalculating path" << std::endl;
00194 #endif
00195
00196
00197 ok = true;
00198 Pathfinder pf;
00199 pf.init(actor);
00200 if (targetitem) {
00201 Item* item = getItem(targetitem);
00202 if (!item)
00203 ok = false;
00204 else {
00205 if(hitmode && !actor->isInCombat()) {
00206
00207 hitmode = false;
00208 }
00209 pf.setTarget(item, hitmode);
00210 item->getLocation(targetx, targety, targetz);
00211 }
00212 } else {
00213 pf.setTarget(targetx, targety, targetz);
00214 }
00215 if (ok)
00216 ok = pf.pathfind(path);
00217
00218 currentstep = 0;
00219 if (!ok) {
00220 perr << "PathfinderProcess: actor " << item_num
00221 << " failed to find path" << std::endl;
00222
00223 result = PATH_FAILED;
00224 terminate();
00225 return false;
00226 }
00227 }
00228
00229 if (currentstep >= path.size()) {
00230 #if 0
00231 pout << "PathfinderProcess: done" << std::endl;
00232 #endif
00233
00234 result = PATH_OK;
00235 terminate();
00236 return false;
00237 }
00238
00239 uint16 animpid = actor->doAnim(path[currentstep].action,
00240 path[currentstep].direction,
00241 path[currentstep].steps);
00242 #if 0
00243 pout << "PathfinderProcess(" << getPid() << "): taking step "
00244 << path[currentstep].action << "," << path[currentstep].direction
00245 << " (animpid=" << animpid << ")" << std::endl;
00246 #endif
00247 currentstep++;
00248
00249 waitFor(animpid);
00250 return true;
00251 }
00252
00253 void PathfinderProcess::saveData(ODataSource* ods)
00254 {
00255 Process::saveData(ods);
00256
00257 ods->write2(targetitem);
00258 ods->write2(static_cast<uint16>(targetx));
00259 ods->write2(static_cast<uint16>(targety));
00260 ods->write2(static_cast<uint16>(targetz));
00261 ods->write1(hitmode ? 1 : 0);
00262 ods->write2(static_cast<uint16>(currentstep));
00263
00264 ods->write2(static_cast<uint16>(path.size()));
00265 for (unsigned int i = 0; i < path.size(); ++i) {
00266 ods->write2(static_cast<uint16>(path[i].action));
00267 ods->write2(static_cast<uint16>(path[i].direction));
00268 }
00269 }
00270
00271 bool PathfinderProcess::loadData(IDataSource* ids, uint32 version)
00272 {
00273 if (!Process::loadData(ids, version)) return false;
00274
00275 targetitem = ids->read2();
00276 targetx = ids->read2();
00277 targety = ids->read2();
00278 targetz = ids->read2();
00279 hitmode = (ids->read1() != 0);
00280 currentstep = ids->read2();
00281
00282 unsigned int pathsize = ids->read2();
00283 path.resize(pathsize);
00284 for (unsigned int i = 0; i < pathsize; ++i) {
00285 path[i].action = static_cast<Animation::Sequence>(ids->read2());
00286 path[i].direction = ids->read2();
00287 }
00288
00289 return true;
00290 }