std::vector<Command> CCommandAI::GetOverlapQueued(const Command& c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); std::vector<Command> v; BuildInfo cbi(c); if (ci != q.begin()) { do { --ci; //iterate from the end and dont check the current order const Command& t = *ci; if (t.params.size() != c.params.size()) continue; if (t.GetID() == c.GetID() || (c.GetID() < 0 && t.GetID() < 0)) { if (c.params.size() == 1) { // assume the param is a unit or feature id if (t.params[0] == c.params[0]) { v.push_back(t); } } else if (c.params.size() >= 3) { // assume c and t are positional commands // NOTE: uses a BuildInfo structure, but <t> can be ANY command BuildInfo tbi; if (tbi.Parse(t)) { const float dist2X = 2.0f * math::fabs(cbi.pos.x - tbi.pos.x); const float dist2Z = 2.0f * math::fabs(cbi.pos.z - tbi.pos.z); const float addSizeX = SQUARE_SIZE * (cbi.GetXSize() + tbi.GetXSize()); const float addSizeZ = SQUARE_SIZE * (cbi.GetZSize() + tbi.GetZSize()); const float maxSizeX = SQUARE_SIZE * std::max(cbi.GetXSize(), tbi.GetXSize()); const float maxSizeZ = SQUARE_SIZE * std::max(cbi.GetZSize(), tbi.GetZSize()); if (cbi.def == NULL) continue; if (tbi.def == NULL) continue; if (((dist2X > maxSizeX) || (dist2Z > maxSizeZ)) && ((dist2X < addSizeX) && (dist2Z < addSizeZ))) { v.push_back(t); } } else { if ((cbi.pos - tbi.pos).SqLength2D() >= (COMMAND_CANCEL_DIST * COMMAND_CANCEL_DIST)) continue; if ((c.options & SHIFT_KEY) != 0 && (c.options & INTERNAL_ORDER) != 0) continue; v.push_back(t); } } } } while (ci != q.begin()); } return v; }
CCommandQueue::iterator CCommandAI::GetCancelQueued(const Command& c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); while (ci != q.begin()) { --ci; //iterate from the end and dont check the current order const Command& c2 = *ci; const int cmdID = c.GetID(); const int cmd2ID = c2.GetID(); const bool attackAndFight = (cmdID == CMD_ATTACK && cmd2ID == CMD_FIGHT && c2.params.size() == 1); if (c2.params.size() != c.params.size()) continue; if ((cmdID == cmd2ID) || (cmdID < 0 && cmd2ID < 0) || attackAndFight) { if (c.params.size() == 1) { // assume the param is a unit-ID or feature-ID if ((c2.params[0] == c.params[0]) && (cmd2ID != CMD_SET_WANTED_MAX_SPEED)) { return ci; } } else if (c.params.size() >= 3) { if (cmdID < 0) { BuildInfo bc1(c); BuildInfo bc2(c2); if (bc1.def == NULL) continue; if (bc2.def == NULL) continue; if (math::fabs(bc1.pos.x - bc2.pos.x) * 2 <= std::max(bc1.GetXSize(), bc2.GetXSize()) * SQUARE_SIZE && math::fabs(bc1.pos.z - bc2.pos.z) * 2 <= std::max(bc1.GetZSize(), bc2.GetZSize()) * SQUARE_SIZE) { return ci; } } else { // assume c and c2 are positional commands const float3& c1p = c.GetPos(0); const float3& c2p = c2.GetPos(0); if ((c1p - c2p).SqLength2D() >= (COMMAND_CANCEL_DIST * COMMAND_CANCEL_DIST)) continue; if ((c.options & SHIFT_KEY) != 0 && (c.options & INTERNAL_ORDER) != 0) continue; return ci; } } } } return q.end(); }
std::vector<Command> CCommandAI::GetOverlapQueued(const Command &c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); std::vector<Command> v; BuildInfo cbi(c); if (ci != q.begin()){ do { ci--; //iterate from the end and dont check the current order const Command& t = *ci; if (((t.id == c.id) || ((c.id < 0) && (t.id < 0))) && (t.params.size() == c.params.size())){ if (c.params.size()==1) { // assume the param is a unit or feature id if (t.params[0] == c.params[0]) { v.push_back(t); } } else if (c.params.size() >= 3) { // assume this means that the first 3 makes a position BuildInfo tbi; if (tbi.Parse(t)) { const float dist2X = 2.0f * fabs(cbi.pos.x - tbi.pos.x); const float dist2Z = 2.0f * fabs(cbi.pos.z - tbi.pos.z); const float addSizeX = SQUARE_SIZE * (cbi.GetXSize() + tbi.GetXSize()); const float addSizeZ = SQUARE_SIZE * (cbi.GetZSize() + tbi.GetZSize()); const float maxSizeX = SQUARE_SIZE * std::max(cbi.GetXSize(), tbi.GetXSize()); const float maxSizeZ = SQUARE_SIZE * std::max(cbi.GetZSize(), tbi.GetZSize()); if (cbi.def && tbi.def && ((dist2X > maxSizeX) || (dist2Z > maxSizeZ)) && ((dist2X < addSizeX) && (dist2Z < addSizeZ))) { v.push_back(t); } } else { if ((cbi.pos - tbi.pos).SqLength2D() < (17.0f * 17.0f)) { v.push_back(t); } } } } } while (ci != q.begin()); } return v; }
void CWaitCommandsAI::ClearUnitQueue(CUnit* unit, const CCommandQueue& queue) { if ((unit->team != gu->myTeam) || waitMap.empty()) { return; } CCommandQueue::const_iterator qit; for (qit = queue.begin(); qit != queue.end(); ++qit) { const Command& cmd = *qit; if ((cmd.GetID() == CMD_WAIT) && (cmd.params.size() == 2)) { const KeyType key = Wait::GetKeyFromFloat(cmd.params[1]); WaitMap::iterator wit = waitMap.find(key); if (wit != waitMap.end()) { wit->second->RemoveUnit(unit); } } } }
/** * @brief Finds the queued command that would be canceled by the Command c * @return An iterator located at the command, or commandQue.end() if no such queued command exsists **/ CCommandQueue::iterator CCommandAI::GetCancelQueued(const Command &c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); while (ci != q.begin()) { ci--; //iterate from the end and dont check the current order const Command& t = *ci; if (((c.id == t.id) || ((c.id < 0) && (t.id < 0)) || (t.id == CMD_FIGHT && c.id == CMD_ATTACK && t.params.size() == 1)) && (t.params.size() == c.params.size())) { if (c.params.size() == 1) { // assume the param is a unit of feature id if ((t.params[0] == c.params[0]) && (t.id != CMD_SET_WANTED_MAX_SPEED)) { return ci; } } else if (c.params.size() >= 3) { if (c.id < 0) { BuildInfo bc(c); BuildInfo bt(t); if (bc.def && bt.def && fabs(bc.pos.x - bt.pos.x) * 2 <= std::max(bc.GetXSize(), bt.GetXSize()) * SQUARE_SIZE && fabs(bc.pos.z - bt.pos.z) * 2 <= std::max(bc.GetZSize(), bt.GetZSize()) * SQUARE_SIZE) { return ci; } } else { // assume this means that the first 3 makes a position float3 cp(c.params[0], c.params[1], c.params[2]); float3 tp(t.params[0], t.params[1], t.params[2]); if ((cp - tp).SqLength2D() < (17.0f * 17.0f)) { return ci; } } } } } return q.end(); }
CCommandQueue::iterator CCommandAI::GetCancelQueued(const Command& c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); while (ci != q.begin()) { --ci; //iterate from the end and dont check the current order const Command& c2 = *ci; const int& cmd_id = c.GetID(); const int& cmd2_id = c2.GetID(); if (((cmd_id == cmd2_id) || ((cmd_id < 0) && (cmd2_id < 0)) || (cmd2_id == CMD_FIGHT && cmd_id == CMD_ATTACK && c2.params.size() == 1)) && (c2.params.size() == c.params.size())) { if (c.params.size() == 1) { // assume the param is a unit-ID or feature-ID if ((c2.params[0] == c.params[0]) && (cmd2_id != CMD_SET_WANTED_MAX_SPEED)) { return ci; } } else if (c.params.size() >= 3) { if (cmd_id < 0) { BuildInfo bc(c); BuildInfo bc2(c2); if (bc.def && bc2.def && fabs(bc.pos.x - bc2.pos.x) * 2 <= std::max(bc.GetXSize(), bc2.GetXSize()) * SQUARE_SIZE && fabs(bc.pos.z - bc2.pos.z) * 2 <= std::max(bc.GetZSize(), bc2.GetZSize()) * SQUARE_SIZE) { return ci; } } else { // assume this means that the first 3 makes a position float3 cp(c.params[0], c.params[1], c.params[2]); float3 c2p(c2.params[0], c2.params[1], c2.params[2]); if ((cp - c2p).SqLength2D() < (17.0f * 17.0f)) { return ci; } } } } } return q.end(); }
int CCommandAI::CancelCommands(const Command &c, CCommandQueue& q, bool& first) { first = false; int cancelCount = 0; while (true) { CCommandQueue::iterator ci = GetCancelQueued(c, q); if (ci == q.end()) { return cancelCount; } first = first || (ci == q.begin()); cancelCount++; CCommandQueue::iterator firstErase = ci; CCommandQueue::iterator lastErase = ci; ci++; if ((ci != q.end()) && (ci->id == CMD_SET_WANTED_MAX_SPEED)) { lastErase = ci; cancelCount++; ci++; } if ((ci != q.end()) && (ci->id == CMD_WAIT)) { waitCommandsAI.RemoveWaitCommand(owner, *ci); lastErase = ci; cancelCount++; ci++; } lastErase++; // STL: erase the range [first, last) q.erase(firstErase, lastErase); if (c.id >= 0) { return cancelCount; // only delete one non-build order } } return cancelCount; }
void CCommandAI::ExecuteRemove(const Command& c) { // disable repeating during the removals const bool prevRepeat = repeatOrders; repeatOrders = false; CCommandQueue* queue = &commandQue; bool facBuildQueue = false; CFactoryCAI* facCAI = dynamic_cast<CFactoryCAI*>(this); if (facCAI) { if (c.options & CONTROL_KEY) { // check the build order facBuildQueue = true; } else { // use the new commands queue = &facCAI->newUnitCommands; } } if ((c.params.size() <= 0) || (queue->size() <= 0)) { return; } // erase commands by a list of command types bool active = false; for (unsigned int p = 0; p < c.params.size(); p++) { const int removeValue = (int)c.params[p]; // tag or id if (facBuildQueue && (removeValue == 0) && !(c.options & ALT_KEY)) { continue; // don't remove tag=0 commands from build queues, they // are used the same way that CMD_STOP is, to void orders } CCommandQueue::iterator ci; do { for (ci = queue->begin(); ci != queue->end(); ++ci) { const Command& qc = *ci; if (c.options & ALT_KEY) { if (qc.id != removeValue) { continue; } } else { if (qc.tag != removeValue) { continue; } } if (qc.id == CMD_WAIT) { waitCommandsAI.RemoveWaitCommand(owner, qc); } if (facBuildQueue) { facCAI->RemoveBuildCommand(ci); ci = queue->begin(); break; // the removal may have corrupted the iterator } if (!facCAI && (ci == queue->begin())) { if (!active) { active = true; FinishCommand(); ci = queue->begin(); break; } active = true; } queue->erase(ci); ci = queue->begin(); break; // the removal may have corrupted the iterator } } while (ci != queue->end()); } repeatOrders = prevRepeat; return; }
void CCommandAI::ExecuteInsert(const Command& c, bool fromSynced) { if (c.params.size() < 3) { return; } // make the command Command newCmd; newCmd.id = (int)c.params[1]; newCmd.options = (unsigned char)c.params[2]; for (int p = 3; p < (int)c.params.size(); p++) { newCmd.params.push_back(c.params[p]); } // validate the command if (!AllowedCommand(newCmd, fromSynced)) { return; } CCommandQueue* queue = &commandQue; bool facBuildQueue = false; CFactoryCAI* facCAI = dynamic_cast<CFactoryCAI*>(this); if (facCAI) { if (c.options & CONTROL_KEY) { // check the build order const map<int, CFactoryCAI::BuildOption>& bOpts = facCAI->buildOptions; if ((newCmd.id != CMD_STOP) && (newCmd.id != CMD_WAIT) && ((newCmd.id >= 0) || (bOpts.find(newCmd.id) == bOpts.end()))) { return; } facBuildQueue = true; } else { // use the new commands queue = &facCAI->newUnitCommands; } } // FIXME: handle CMD_LOOPBACKATTACK, etc... CCommandQueue::iterator insertIt = queue->begin(); if (c.options & ALT_KEY) { // treat param0 as a position int pos = (int)c.params[0]; const unsigned int qsize = queue->size(); if (pos < 0) { pos = qsize + pos + 1; // convert the negative index if (pos < 0) { pos = 0; } } if (pos > qsize) { pos = qsize; } std::advance(insertIt, pos); } else { // treat param0 as a command tag const unsigned int tag = (unsigned int)c.params[0]; CCommandQueue::iterator ci; bool found = false; for (ci = queue->begin(); ci != queue->end(); ++ci) { const Command& qc = *ci; if (qc.tag == tag) { insertIt = ci; found = true; break; } } if (!found) { return; } if ((c.options & RIGHT_MOUSE_KEY) && (insertIt != queue->end())) { insertIt++; // insert after the tagged command } } if (facBuildQueue) { facCAI->InsertBuildCommand(insertIt, newCmd); if (!owner->stunned) { SlowUpdate(); } return; } // shutdown the current order if the insertion is at the beginning if (!queue->empty() && (insertIt == queue->begin())) { inCommand = false; targetDied = false; unimportantMove = false; orderTarget = NULL; const Command& cmd = commandQue.front(); eoh->CommandFinished(*owner, cmd); eventHandler.UnitCmdDone(owner, cmd.id, cmd.tag); } queue->insert(insertIt, newCmd); if (!owner->stunned) { SlowUpdate(); } return; }
void CCommandAI::ExecuteRemove(const Command& c) { CCommandQueue* queue = &commandQue; CFactoryCAI* facCAI = dynamic_cast<CFactoryCAI*>(this); // if false, remove commands by tag const bool removeByID = (c.options & ALT_KEY); // disable repeating during the removals const bool prevRepeat = repeatOrders; // erase commands by a list of command types bool active = false; bool facBuildQueue = false; if (facCAI) { if (c.options & CONTROL_KEY) { // keep using the build-order queue facBuildQueue = true; } else { // use the command-queue for new units queue = &facCAI->newUnitCommands; } } if ((c.params.size() <= 0) || (queue->size() <= 0)) { return; } repeatOrders = false; for (unsigned int p = 0; p < c.params.size(); p++) { const int removeValue = c.params[p]; // tag or id if (facBuildQueue && !removeByID && (removeValue == 0)) { // don't remove commands with tag 0 from build queues, they // are used the same way that CMD_STOP is (to void orders) continue; } CCommandQueue::iterator ci; do { for (ci = queue->begin(); ci != queue->end(); ++ci) { const Command& qc = *ci; if (removeByID) { if (qc.GetID() != removeValue) { continue; } } else { if (qc.tag != removeValue) { continue; } } if (qc.GetID() == CMD_WAIT) { waitCommandsAI.RemoveWaitCommand(owner, qc); } if (facBuildQueue) { // if ci == queue->begin() and !queue->empty(), this pop_front()'s // via CFAI::ExecuteStop; otherwise only modifies *ci (not <queue>) if (facCAI->RemoveBuildCommand(ci)) { ci = queue->begin(); break; } } if (!facCAI && (ci == queue->begin())) { if (!active) { active = true; FinishCommand(); ci = queue->begin(); break; } active = true; } queue->erase(ci); ci = queue->begin(); // the removal may have corrupted the iterator break; } } while (ci != queue->end()); } repeatOrders = prevRepeat; }
//------------------------------------------ bool CEngine::Initialize(const wchar* settings/*="game.ini"*/, bool customWindow/*=false*/, sDisplayProperties *dp/*=NULL*/){ assertd(s_bInit==false, "DOUBLE ENGINE INITIALIZATION!"); s_bInit = true; //predict :-P // initialize random generator srand( (unsigned int)milisec() ); cInternalWindow()->BeginSplash(); // memory leaks detection #if defined(_DEBUG) && defined(_MSC_VER) && _MSC_VER >= 800 _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); //_CrtSetBreakAlloc(23296); #endif // --------------------------------------------------- // QUEUE TESTS CON(MSG_INFO, _W("------- Command Queue Test -------")); CCommandQueue q; DWORD tim; for (int t=0; t<10; t++) { tim = GetTickCount(); // FILL IN QUEUE for (int i=0; i<20000; i++) { sE2RCanvasDesc *cd; q.Enqueue(NULL, CQI_ENGINE2RENDERER_CANVAS_CREATE, (void*&)cd, sizeof(sE2RCanvasDesc)); cd->handle = 0; } CON(MSG_INFO, _W("Iteration #%d: Enqueue %d ms"), t, GetTickCount()-tim ); // DEQUEUE unsigned int cqi; const void* optr; IQueueCommandReceiver *recv; tim = GetTickCount(); while (q.Dequeue(cqi, optr, recv)) { switch(cqi) { case CQI_ENGINE2RENDERER_CANVAS_CREATE: { sE2RCanvasDesc *cd = (sE2RCanvasDesc *)optr; } break; } } CON(MSG_INFO, _W("Iteration #%d: Dequeue %d ms"), t, GetTickCount()-tim ); } CON(MSG_INFO, _W("----------------------------------")); // --------------------------------------------------- // --- WRITE INFO ABOUT LIBRARIES AND MODULES I_DebugPrint( ConsoleMsg ); CON(MSG_INFO, _W("= %s %s build %d initialization ="), _W(P3DNAME), sizeof(void*)==8?_W("x64"):_W("x86"), GetBuildNum()); if (sizeof(wchar)>1) CON(MSG_INFO, _W("Unicode support \x263A")); else CON(MSG_INFO, _W("Multibyte character set")); // --- LOAD SETTINGS m_szSettings = new wchar[wstrlen(settings)+1]; wstrcpy(m_szSettings, settings); cConfig()->Load(m_szSettings); //cConfig()->Save(m_szSettings); // --- INITIALIZE SCRIPT SYSTEM CON(MSG_INFO, _W("Script system initialization")); cScriptEngine()->Initialize(); // --- LOAD KEY BINDINGS cInputManager()->Assign(_W("GUI_CURSOR"), WE_MOUSE_MOTION, 0); cInputManager()->Assign(_W("GUI_SELECT"), WE_MOUSE_DOWN, 0); cInputManager()->Save(_W("keys.ini")); // TODO: FIXME: What about load? :D // --- CREATE MAIN WINDOW Vec2i mainWindowSize(800,600); bool initFullscreen = false; if (customWindow) { // use primary screen resolution for frame buffer // TODO: multiplatform #ifdef _WIN32 mainWindowSize.x = GetSystemMetrics(SM_CXSCREEN); mainWindowSize.y = GetSystemMetrics(SM_CYSCREEN); #endif } else { if (dp) { // use user-defined resolution initFullscreen = dp->Fullscreen; mainWindowSize.x = dp->HorRes; mainWindowSize.y = dp->VertRes; } else { // use settings initFullscreen = svFullscreen.GetBool(); mainWindowSize.x = svResolutionX.GetInt(); mainWindowSize.y = svResolutionY.GetInt(); } } cInternalWindow()->Create(mainWindowSize); //Init the internal input system cInternalInput()->Init( cInternalWindow()->GetHandle() ); //Init the Filesystem cFilesystem()->Init(); // --- LOAD SELECTED MODULES s_pRenderer = (IRenderer*)I_GetModule(_W("renderer"), svRenderer.GetString()); if (!s_pRenderer) CON(MSG_ERR_FATAL, _W("Cannot load renderer module. It is a core module, cannot continue!")); s_pSound = (ISoundEngine*)I_GetModule(_W("sound"), svSound.GetString()); if (!s_pSound) CON(MSG_ERR_FATAL, _W("Cannot load sound module. It is a core module, cannot continue!")); s_pPhys = (IPhysEngine*)I_GetModule(_W("physics"), svPhysics.GetString()); if (!s_pPhys) CON(MSG_ERR_FATAL, _W("Cannot load phys module. It is a core module, cannot continue!")); s_pFS = (IFileSystem*)I_GetModule(_W("filesystem"), svFileSystem.GetString()); if (!s_pFS) CON(MSG_ERR_FATAL, _W("Cannot load filesystem module. It is a core module, cannot continue!")); s_pGUI = (IGUI*)I_GetModule(_W("gui"), svGUI.GetString()); if (!s_pGUI) CON(MSG_ERR_FATAL, _W("Cannot load GUI module. It is a core module, cannot continue!")); m_bModulesLoaded=true; // ==== INITIALIZE MODULES ==== s_pRenderer->Initialize(this, &m_queueRenderer); bool ret = s_pRenderer->iGraphicsDevice()->Initialize(mainWindowSize.x, mainWindowSize.y, initFullscreen, cInternalWindow()->GetHandle()); if (!ret) { CON(MSG_ERR_FATAL, _W("Failed to initialize graphics device!")); } // ===== SERIALIZATION DEBUG AND TEST ======= Scene scene; //scene.Save(s_pFS, _W("scenes/test.robject"), iConsole()); //CModel model; /*model = (Model*)cObjectManager()->CreateObject( _W("Model") ); MeshData md; MeshSubset ms; // Material m; // ms.Material = m; ms.NumTriangles = 1; ms.StartIndex = 0; //ms.StartVertex = 0; md.Subsets.AddEx(ms); md.Indices.AddEx(0); md.Indices.AddEx(1); md.Indices.AddEx(2); md.NumIndices = 3; MeshVertexData mvd; mvd.Usage = _W("P3DVU_POSITION"); mvd.DataSize = 3; mvd.Float3.AddEx(Vec3Param(0.0f, 0.0f, 0.0f)); mvd.Float3.AddEx(Vec3Param(0.0f, 1.0f, 0.0f)); mvd.Float3.AddEx(Vec3Param(1.0f, 1.0f , 0.0f)); md.DataStreams.AddEx(mvd); md.NumVerts = 3; model->LODs.AddEx(md); model->Save(s_pFS, _W("triangle.robject"), iConsole()); model->PreCache();*/ // =========================================== bool initOK=true; initOK &= s_pSound->Initialize(this); initOK &= s_pPhys->Initialize(this); initOK &= s_pFS->Initialize(this); initOK &= s_pGUI->Initialize(this); if (!initOK) CON(MSG_ERR_FATAL, _W("Failed to initialize some core module(s)! Cannot continue. For more details see console.htm.")); cSceneManager()->Create(); cConsole()->InitializeGUI(); // at this time, coz it uses GUI module and it must be initialized ;) // FIXME: register engine to script, temporary here /*using namespace luabind; lua_State* L = cScriptEngine()->GetLVM(); module(L) [ class_<CEngine>("Engine") .scope [ def("GetBuildNum", &CEngine::GetBuildNum ) ] ];*/ // load bootstrap script cScriptEngine()->LoadScript(_W("scripts/bootstrap.rscript")); // DEBUG TESTING OF QUEUE TO RENDERER sE2RCanvasDesc* canvas; EnqueueMessage( MC_RENDERER, this, CQI_ENGINE2RENDERER_CANVAS_CREATE, (void*&)canvas, sizeof(sE2RCanvasDesc) ); canvas->handle = cInternalWindow()->GetHandle(); canvas->size = Vec2i(800,600); canvas->windowed = !initFullscreen; //Sleep(10000); cInternalWindow()->EndSplash(); cInternalWindow()->SetVisible(true); //Filesystem test /*UINT oSize; void *lData=0; if(cFilesystem()->Load(_W("scripts.bootstrap"), &lData, oSize)==P3D_FILERESULT_OK) cFilesystem()->FreeLoadedData(lData); const char* testStr = "this is a test string"; cFilesystem()->Save(_W("scripts.fstest"), testStr, sizeof(char)*strlen(testStr));*/ return true; }