Gdiplus::Color CBottomBaseView::GetFontColorForSmallButton(void) { AssertBotE((CBotEDoc*)GetDocument()); CMajor* pPlayer = m_pPlayersRace; AssertBotE(pPlayer); Color color; color.SetFromCOLORREF(pPlayer->GetDesign()->m_clrSmallBtn); return color; }
/// Funktion lädt die rassenspezifischen Grafiken. void CShipDesignMenuView::LoadRaceGraphics() { CBotEDoc* pDoc = resources::pDoc; ASSERT(pDoc); CMajor* pMajor = m_pPlayersRace; ASSERT(pMajor); CreateButtons(); CString sPrefix = pMajor->GetPrefix(); bg_designmenu = pDoc->GetGraphicPool()->GetGDIGraphic("Backgrounds\\" + sPrefix + "designmenu.boj"); }
/// Funktion überprüft ob das in der Designansicht angeklickte Schiff in einem unserer Systeme gerade gebaut wird /// Man benötigt diesen Check da man keine Schiffe ändern kann, welche gerade gebaut werden. /// @param pShipInfo Zeiger des zu prüfenden Schiffes aus der Schiffsliste /// @return CString mit dem Namen des Systems, wird das Schiff nirgends gebaut ist der String leer CString CShipDesignMenuView::CheckIfShipIsBuilding(const CShipInfo* pShipInfo) const { if (!pShipInfo) return ""; CBotEDoc* pDoc = resources::pDoc; ASSERT(pDoc); CMajor* pMajor = m_pPlayersRace; ASSERT(pMajor); if (!pMajor) return ""; USHORT ID = pShipInfo->GetID(); // alle eigenen Systeme durchgehen und schauen, ob an erster Stelle in der Bauliste so ein Schiff steht for (int y = 0; y < STARMAP_SECTORS_VCOUNT; y++) for (int x = 0; x < STARMAP_SECTORS_HCOUNT; x++) if (pDoc->GetSystem(x,y).GetOwnerOfSystem() == pMajor->GetRaceID()) for (int i = 0; i < ALE; i++) if (pDoc->GetSystem(x,y).GetAssemblyList()->GetAssemblyListEntry(i) == ID) return pDoc->GetSector(x,y).GetName(); return ""; }
void CIntelBottomView::OnDraw(CDC* dc) { CBotEDoc* pDoc = resources::pDoc; AssertBotE(pDoc); if (!pDoc->m_bDataReceived) return; CMajor* pMajor = m_pPlayersRace; AssertBotE(pMajor); if (!pMajor) return; // TODO: add draw code here // Doublebuffering wird initialisiert CMyMemDC pDC(dc); CRect client; GetClientRect(&client); // Graphicsobjekt, in welches gezeichnet wird anlegen Graphics g(pDC->GetSafeHdc()); g.Clear(static_cast<Gdiplus::ARGB>(Color::Black)); g.SetSmoothingMode(SmoothingModeHighSpeed); g.SetInterpolationMode(InterpolationModeLowQuality); g.SetPixelOffsetMode(PixelOffsetModeHighSpeed); g.SetCompositingQuality(CompositingQualityHighSpeed); g.ScaleTransform((REAL)client.Width() / (REAL)m_TotalSize.cx, (REAL)client.Height() / (REAL)m_TotalSize.cy); CString fontName = ""; Gdiplus::REAL fontSize = 0.0; StringFormat fontFormat; SolidBrush fontBrush(static_cast<Gdiplus::ARGB>(Color::White)); Color color; color.SetFromCOLORREF(pMajor->GetDesign()->m_clrGalaxySectorText); fontBrush.SetColor(color); Bitmap* graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Backgrounds\\" + pMajor->GetPrefix() + "diplomacyV3.boj"); // Grafik zeichnen if (graphic) { g.DrawImage(graphic, 0, 0, 1075, 249); graphic = NULL; } // Nur in bestimmten Submenüs werden in der View3 Berichte angezeigt BYTE curIntelSubMenu = resources::pMainFrame->GetSubMenu(RUNTIME_CLASS(CIntelMenuView)); if (curIntelSubMenu == 4 || curIntelSubMenu == 5) { CRect r; r.SetRect(0,0,m_TotalSize.cx,m_TotalSize.cy); short n = pMajor->GetEmpire()->GetIntelligence()->GetIntelReports()->GetActiveReport(); if (n != -1) { CFontLoader::CreateGDIFont(pMajor, 4, fontName, fontSize); fontFormat.SetAlignment(StringAlignmentNear); fontFormat.SetLineAlignment(StringAlignmentNear); fontFormat.SetFormatFlags(StringFormatFlagsNoWrap); CIntelObject* report = pMajor->GetEmpire()->GetIntelligence()->GetIntelReports()->GetReport(n); CString s; if (report->GetIsSpy()) s = CLoc::GetString("SPY"); else s = CLoc::GetString("SABOTAGE"); g.DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40, 40, r.right-100, r.bottom-20), &fontFormat, &fontBrush); CFontLoader::CreateGDIFont(pMajor, 2, fontName, fontSize); fontBrush.SetColor(Color(200,200,250)); fontFormat.SetFormatFlags(!StringFormatFlagsNoWrap); if (report->GetOwner() == pMajor->GetRaceID()) s = *report->GetOwnerDesc(); else s = *report->GetEnemyDesc(); g.DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40, 100, r.right-250, r.bottom-20), &fontFormat, &fontBrush); } } g.ReleaseHDC(pDC->GetSafeHdc()); }
void CRandomEventCtrl::CalcShipEvents() const { if (!IsActivated()) return; CBotEDoc* pDoc = resources::pDoc; AssertBotE(pDoc); // Hüllenvirus for (int x = 0; x < STARMAP_SECTORS_HCOUNT; x++) { for (int y = 0; y < STARMAP_SECTORS_VCOUNT; y++) { // 0.1% Wahrscheinlichkeit für einen Hüllenvirus pro Sektor if (rand()%1000 != 0) continue; // gibt es keine Schiffe im Sektor, dann macht ein Hüllenvirus auch nichts CSector* pSector = &(pDoc->GetSystem(x, y)); if (!pSector->GetIsShipInSector()) continue; // allen Schiffe im Sektor die Hülle auf 1 reduzieren (außer Aliens) for (CShipMap::iterator i = pDoc->m_ShipMap.begin(); i != pDoc->m_ShipMap.end(); ++i) { if (i->second->IsAlien()) continue; if (i->second->GetCo() != pSector->GetCo()) continue; int nCurrentHull = i->second->GetHull()->GetCurrentHull(); i->second->GetHull()->SetCurrentHull(-(nCurrentHull - 1), true); // allen Schiffen in der Flotte ebenfalls die Hülle auf 1 setzen for (CShips::iterator j = i->second->begin(); j != i->second->end(); ++j) { nCurrentHull = j->second->GetHull()->GetCurrentHull(); j->second->GetHull()->SetCurrentHull(-(nCurrentHull - 1), true); } } // Nachrichten an alle Major welche Schiffe in diesem Sektor hatten const std::map<CString, CMajor*>* pmMajors = pDoc->GetRaceCtrl()->GetMajors(); for (map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) { if (!pSector->GetOwnerOfShip(it->first, true)) continue; CMajor* pMajor = it->second; if (!pMajor) continue; const CString& sSectorName = pSector->CoordsName(true); CString sMessageText = CLoc::GetString("EVENTHULLVIRUS", false, sSectorName); CEmpireNews message; message.CreateNews(sMessageText,EMPIRE_NEWS_TYPE::MILITARY,pSector->GetName(),pSector->GetCo()); pMajor->GetEmpire()->AddMsg(message); if (pMajor->IsHumanPlayer()) { resources::pClientWorker->SetToEmpireViewFor(*pMajor); pMajor->GetEmpire()->PushEvent(boost::make_shared<CEventRandom>(pMajor->GetRaceID(), "HullVirus", sMessageText, "")); } } } } }
void CResearchBottomView::OnDraw(CDC* dc) { CBotEDoc* pDoc = resources::pDoc; AssertBotE(pDoc); if (!pDoc->m_bDataReceived) return; CMajor* pMajor = m_pPlayersRace; AssertBotE(pMajor); if (!pMajor) return; // TODO: add draw code here // Doublebuffering wird initialisiert CMyMemDC pDC(dc); CRect client; GetClientRect(&client); // Graphicsobjekt, in welches gezeichnet wird anlegen Graphics g(pDC->GetSafeHdc()); g.Clear(static_cast<Gdiplus::ARGB>(Color::Black)); g.SetSmoothingMode(SmoothingModeHighSpeed); g.SetInterpolationMode(InterpolationModeLowQuality); g.SetPixelOffsetMode(PixelOffsetModeHighSpeed); g.SetCompositingQuality(CompositingQualityHighSpeed); g.ScaleTransform((REAL)client.Width() / (REAL)m_TotalSize.cx, (REAL)client.Height() / (REAL)m_TotalSize.cy); CString fontName = ""; Gdiplus::REAL fontSize = 0.0; StringFormat fontFormat; SolidBrush fontBrush(static_cast<Gdiplus::ARGB>(Color::White)); CRect rect; rect.SetRect(0,0,m_TotalSize.cx,m_TotalSize.cy); CString sPrefix = pMajor->GetPrefix(); Color color; color.SetFromCOLORREF(pMajor->GetDesign()->m_clrGalaxySectorText); fontBrush.SetColor(color); Bitmap* graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Backgrounds\\" + sPrefix + "researchV3.boj"); // gibt es keine Spezialforschung zur Auswahl, so wird auf Standardanzeige umgestellt if (m_nCurrentTech == 6 && pMajor->GetEmpire()->GetResearch()->GetUniqueReady() == TRUE) m_nCurrentTech = 0; // Grafik zeichnen if (graphic) { g.DrawImage(graphic, 0, 0, 1075, 249); graphic = NULL; } switch(m_nCurrentTech) { case 0: graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Research\\biotech.bop"); break; case 1: graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Research\\energytech.bop"); break; case 2: graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Research\\computertech.bop"); break; case 3: graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Research\\propulsiontech.bop"); break; case 4: graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Research\\constructiontech.bop"); break; case 5: graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Research\\weapontech.bop"); break; case 6: graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Research\\specialtech.bop"); break; } if (graphic) { g.DrawImage(graphic, 790, 25, 240, 200); graphic = NULL; } // Name und Beschreibung der Forschung anzeigen CFontLoader::CreateGDIFont(pMajor, 4, fontName, fontSize); fontFormat.SetAlignment(StringAlignmentNear); fontFormat.SetLineAlignment(StringAlignmentNear); fontFormat.SetFormatFlags(StringFormatFlagsNoWrap); CString s; if (m_nCurrentTech != 6) s = pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetTechName(m_nCurrentTech); else s = pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetCurrentResearchComplex()->GetComplexName(); g.DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40, 30, rect.right-325, rect.bottom), &fontFormat, &fontBrush); CFontLoader::CreateGDIFont(pMajor, 2, fontName, fontSize); fontBrush.SetColor(Color(200,200,250)); fontFormat.SetFormatFlags(!StringFormatFlagsNoWrap); if (m_nCurrentTech != 6) s = pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetTechDescription(m_nCurrentTech); else s = pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetCurrentResearchComplex()->GetComplexDescription(); g.DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40, 100, rect.right-325, rect.bottom), &fontFormat, &fontBrush); g.ReleaseHDC(pDC->GetSafeHdc()); }
////////////////////////////////////////////////////////////////////// // sonstige Funktionen ////////////////////////////////////////////////////////////////////// /// Diese Funktion erteilt allen Schiffen aller computergesteuerten Rassen Befehle. void CShipAI::CalculateShipOrders(CSectorAI* SectorAI) { ASSERT(SectorAI); m_pSectorAI = SectorAI; // einen möglichen Angriffssektor berechnen lassen CalcAttackSector(); // danach einen möglichen Bombardierungssektor finden CalcBombardSector(); for(CShipMap::iterator i = m_pDoc->m_ShipMap.begin(); i != m_pDoc->m_ShipMap.end(); ++i) { if(i->second->IsAlien()) { CalculateAlienShipOrders(*i->second); continue; } const CString& sOwner = i->second->GetOwnerOfShip(); CMajor* pOwner = dynamic_cast<CMajor*>(m_pDoc->GetRaceCtrl()->GetRace(sOwner)); // gilt erstmal nur für Majors if (!pOwner || !pOwner->IsMajor()) continue; // gilt nicht für menschliche Spieler if (pOwner->AHumanPlays()) continue; // Flotte versuchen zu erstellen DoMakeFleet(i); // Vielleicht haben unsere Schiffe ein Ziel, welches sie angreifen müssen/können if (DoAttackMove(i->second, pOwner)) { DoCamouflage(i->second); continue; } // haben Kolonieschiffe einen Sektor zum Terraformen als Ziel, welcher kurz zuvor aber von einer // anderen Rasse weggeschnappt wurde, so wird ihr Kurs gelöscht if (i->second->GetShipType() == SHIP_TYPE::COLONYSHIP) { CPoint ptKO = i->second->GetKO(); // hat das Kolonieschiff den Befehl zum Terraformen, so wird dieser rückgängig gemacht, wenn der Sektor // schon einer anderen Rasse gehört if (i->second->GetCurrentOrder() == SHIP_ORDER::TERRAFORM) { if (m_pDoc->GetSector(ptKO.x, ptKO.y).GetOwnerOfSector() != "" && m_pDoc->GetSector(ptKO.x, ptKO.y).GetOwnerOfSector() != sOwner) { // Terraforming abbrechen i->second->UnsetCurrentOrder(); i->second->SetCombatTactic(COMBAT_TACTIC::CT_AVOID); } } CPoint ptTarget = i->second->GetTargetKO(); // nur wenn der Sektor noch niemandem gehört bzw. uns selbst ist, sollen Planeten terraformt werden if (ptTarget != CPoint(-1,-1) && m_pDoc->GetSector(ptTarget.x, ptTarget.y).GetOwnerOfSector() != "" && m_pDoc->GetSector(ptTarget.x, ptTarget.y).GetOwnerOfSector() != sOwner) { // nicht weiter fliegen und Kurs löschen i->second->SetTargetKO(CPoint(-1, -1)); i->second->GetPath()->RemoveAll(); } } // exisitiert kein aktueller Kurs, so wird dieser hier versucht dem Schiff zu erteilen if (i->second->GetPath()->GetSize() == 0) { // Scouts und Kriegsschiffe fliegen zuerst einmal zu den Minorracesystemen if (i->second->GetShipType() > SHIP_TYPE::COLONYSHIP) { // Zeiger auf Vektor mit Minorracessektoren holen vector<CPoint>* vMinorraceSectors = m_pSectorAI->GetMinorraceSectors(sOwner); bool bSet = false; int nCount = vMinorraceSectors->size() * 2; while (vMinorraceSectors->size() && nCount--) { int j = rand()%vMinorraceSectors->size(); CPoint ko = vMinorraceSectors->at(j); // Wenn Gefahr der anderen Rassen kleiner als die der meinen ist if (m_pSectorAI->GetCompleteDanger(sOwner, ko) == NULL || (m_pSectorAI->GetCompleteDanger(sOwner, ko) <= m_pSectorAI->GetDangerOnlyFromCombatShips(sOwner, i->second->GetKO()))) if (pOwner->GetStarmap()->GetRange(ko) <= i->second->GetRange(false)) { // Zielkoordinate für das Schiff setzen i->second->SetTargetKO(ko); MYTRACE("shipai")(MT::LEVEL_DEBUG, "Race %s: Ship to Minor: %s (%s) - Target: %d,%d\n",sOwner, i->second->GetShipName(), i->second->GetShipTypeAsString(), ko.x,ko.y); vMinorraceSectors->erase(vMinorraceSectors->begin() + j--); bSet = true; break; } } if (bSet) { DoCamouflage(i->second); continue; } } // Kolonieschiffe zum Terraformen schicken. Andere Schiffe fliegen manchmal auch dort hin, wenn // sie gerade keinen anderen Flugauftrag haben. if (i->second->GetShipType() >= SHIP_TYPE::COLONYSHIP && i->second->GetCurrentOrder() != SHIP_ORDER::TERRAFORM) { // Zeiger auf Vektor mit Terraformsektoren holen vector<CSectorAI::SectorToTerraform>* vSectorsToTerrform = m_pSectorAI->GetSectorsToTerraform(sOwner); for (UINT j = 0; j < vSectorsToTerrform->size(); j++) { CPoint ko = vSectorsToTerrform->at(j).p; // Wenn das Kolonieschiff schon auf einem Sektor für unser Terraforming steht, so fliegt es nicht weiter if (i->second->GetShipType() == SHIP_TYPE::COLONYSHIP && i->second->GetKO() == ko) break; // Wenn Gefahr der anderen Rassen kleiner als die der meinen ist if (m_pSectorAI->GetCompleteDanger(sOwner, ko) == NULL || (m_pSectorAI->GetCompleteDanger(sOwner, ko) < m_pSectorAI->GetDanger(sOwner, i->second->GetKO()))) { if (pOwner->GetStarmap()->GetRange(ko) <= i->second->GetRange(false)) { // Zielkoordinate für das Schiff setzen i->second->SetTargetKO(ko == i->second->GetKO() ? CPoint(-1, -1) : ko); MYTRACE("shipai")(MT::LEVEL_DEBUG, "Race %s: Ship %s (%s) has terraforming target: %d,%d\n",sOwner, i->second->GetShipName(), i->second->GetShipTypeAsString(), ko.x,ko.y); break; } } } } // Truppentransporter zu einem möglichen Sektor fliegen lassen um dort einen Außenposten bauen zu können if (m_pSectorAI->GetStationBuildSector(sOwner).points > MINBASEPOINTS && i->second->GetCurrentOrder() != SHIP_ORDER::BUILD_OUTPOST) { // nur Truppentransporter oder andere Schiffe ohne Ziel fliegen zu diesem Punkt, niemals aber // Kolonieschiffe if (i->second->GetShipType() == SHIP_TYPE::TRANSPORTER || (i->second->GetShipType() != SHIP_TYPE::COLONYSHIP && !i->second->HasTarget())) { CPoint ko(m_pSectorAI->GetStationBuildSector(sOwner).position.x, m_pSectorAI->GetStationBuildSector(sOwner).position.y); // Wenn Gefahr der anderen Rassen kleiner als die der meinen ist if (m_pSectorAI->GetCompleteDanger(sOwner, ko) == 0 || (m_pSectorAI->GetCompleteDanger(sOwner, ko) < m_pSectorAI->GetDanger(sOwner, i->second->GetKO()))) { if (pOwner->GetStarmap()->GetRange(ko) <= i->second->GetRange(false)) { // Zielkoordinate für das Schiff setzen i->second->SetTargetKO(ko == i->second->GetKO() ? CPoint(-1, -1) : ko); MYTRACE("shipai")(MT::LEVEL_DEBUG, "Race %s: Ship %s (%s) has stationbuild target: %d,%d\n",sOwner, i->second->GetShipName(), i->second->GetShipTypeAsString(), ko.x,ko.y); } } } } DoCamouflage(i->second); if (m_pDoc->GetSector(i->second->GetKO().x, i->second->GetKO().y).GetSunSystem()) { if (!DoTerraform(i->second)) DoColonize(i->second); } DoStationBuild(i->second); } else { DoCamouflage(i->second); } } }
void CDiplomacyBottomView::OnDraw(CDC* dc) { CBotEDoc* pDoc = resources::pDoc; AssertBotE(pDoc); if (!pDoc->m_bDataReceived) return; CMajor* pMajor = m_pPlayersRace; AssertBotE(pMajor); if (!pMajor) return; // TODO: add draw code here // Doublebuffering wird initialisiert CMyMemDC pDC(dc); CRect client; GetClientRect(&client); // Graphicsobjekt, in welches gezeichnet wird anlegen Graphics g(pDC->GetSafeHdc()); g.Clear(static_cast<Gdiplus::ARGB>(Color::Black)); g.SetSmoothingMode(SmoothingModeHighSpeed); g.SetInterpolationMode(InterpolationModeLowQuality); g.SetPixelOffsetMode(PixelOffsetModeHighSpeed); g.SetCompositingQuality(CompositingQualityHighSpeed); g.ScaleTransform((REAL)client.Width() / (REAL)m_TotalSize.cx, (REAL)client.Height() / (REAL)m_TotalSize.cy); CString fontName = ""; Gdiplus::REAL fontSize = 0.0; StringFormat fontFormat; SolidBrush fontBrush(static_cast<Gdiplus::ARGB>(Color::White)); // Soll was über die Diplomatie angezeigt werden CRect rect; rect.SetRect(0,0,m_TotalSize.cx,m_TotalSize.cy); CString sPrefix = pMajor->GetPrefix(); Color color; color.SetFromCOLORREF(pMajor->GetDesign()->m_clrGalaxySectorText); fontBrush.SetColor(color); Bitmap* graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Backgrounds\\" + sPrefix + "diplomacyV3.boj"); // Grafik zeichnen if (graphic) { g.DrawImage(graphic, 0, 0, 1075, 249); graphic = NULL; } CFontLoader::CreateGDIFont(pMajor, 4, fontName, fontSize); fontFormat.SetAlignment(StringAlignmentNear); fontFormat.SetLineAlignment(StringAlignmentNear); fontFormat.SetFormatFlags(StringFormatFlagsNoWrap); g.DrawString(CComBSTR(m_strHeadLine), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40, 30, rect.right, rect.bottom), &fontFormat, &fontBrush); if (m_strText.IsEmpty()) g.DrawString(CComBSTR(CLoc::GetString("NO_DIPLOMATIC_NEWS")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40, 30, rect.right, rect.bottom), &fontFormat, &fontBrush); m_strHeadLine = ""; CFontLoader::CreateGDIFont(pMajor, 2, fontName, fontSize); fontBrush.SetColor(Color(200,200,250)); fontFormat.SetFormatFlags(!StringFormatFlagsNoWrap); g.DrawString(CComBSTR(m_strText), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40, 100, rect.right-250, rect.bottom), &fontFormat, &fontBrush); g.ReleaseHDC(pDC->GetSafeHdc()); }
////////////////////////////////////////////////////////////////////// // sonstige Funktionen ////////////////////////////////////////////////////////////////////// /// Funktion berechnet den Umgang mit dem Geheimdienst für die KI. Sie trifft Zuteilungen für die einzelnen Rassen. void CIntelAI::CalcIntelligence(CBotEDoc* pDoc) { AssertBotE(pDoc); // Struktur für eine Liste mit Rassen-ID und Geheimdienstpunkten struct INTELLIST { CString sRace; UINT points; bool operator< (const INTELLIST& elem2) const { return points < elem2.points;} bool operator> (const INTELLIST& elem2) const { return points > elem2.points;} INTELLIST() : sRace(""), points(0) {} INTELLIST(const CString& _sRace, UINT _points) : sRace(_sRace), points(_points) {} }; // produzierte Geheimdienstpunkte und Punkte aus allen Geheimdienstlagern einer Rasse zusammenaddieren CArray<INTELLIST> intellist; std::map<CString, CMajor*>* pmMajors = pDoc->GetRaceCtrl()->GetMajors(); for (std::map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) { CIntelligence* pIntel = it->second->GetEmpire()->GetIntelligence(); UINT points = pIntel->GetSecurityPoints() + pIntel->GetInnerSecurityStorage(); for (map<CString, CMajor*>::const_iterator itt = pmMajors->begin(); itt != pmMajors->end(); ++itt) if (itt->first != it->first) points += pIntel->GetSPStorage(0, itt->first) + pIntel->GetSPStorage(1, itt->first); intellist.Add(INTELLIST(it->first, points)); } // nun Feld nach den gesammten Geheimdienstpunkten absteigend sortiren lassen. c_arraysort<CArray<INTELLIST>, INTELLIST> (intellist, sort_desc); // unere Priorität ist der Index der Rasse im Feld. // wenn die Punkte sich nicht mehr als 10% bzw. 100SP unterscheiden, dann wird die Priorität des vorherigen // Indexes benutzt. m_byIntelPrio[intellist.GetAt(0).sRace] = rand()%2; for (int i = 1; i < intellist.GetSize(); i++) // beim zweiten Index starten! Da das erste Element eine 0er Priorität hat { if (intellist.GetAt(i-1).points - intellist.GetAt(i).points > 100 && (intellist.GetAt(i).points * 100 / (intellist.GetAt(i-1).points+1) < 90)) m_byIntelPrio[intellist.GetAt(i).sRace] = i; // ansonsten ist die Priorität der des Vorgängers else m_byIntelPrio[intellist.GetAt(i).sRace] = m_byIntelPrio[intellist.GetAt(i-1).sRace]; } // jeder Geheimdienstbericht mit uns als Ziel aus den letzten 5 Runden erhöht die Priorität nochmal um eins, sofern // es sich dabei um eine Sabotageaktion handelte std::map<CString, int> badReports; for (std::map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) if (it->second->AHumanPlays() == false) { CIntelligence* pIntel = it->second->GetEmpire()->GetIntelligence(); for (int l = 0; l < pIntel->GetIntelReports()->GetNumberOfReports(); l++) { CIntelObject* intelObj = pIntel->GetIntelReports()->GetReport(l); if (intelObj->GetEnemy() == it->first && pDoc->GetCurrentRound() - intelObj->GetRound() < 6 && intelObj->GetIsSabotage()) badReports[it->first] += 1; } m_byIntelPrio[it->first] += badReports[it->first]; } for (std::map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) MYTRACE("intelai")(MT::LEVEL_INFO, "Intel-AI: Intel Prio of %s is %d\n", it->first, m_byIntelPrio[it->first]); // nun liegen die Prioritäten und die Listen mit den Punkten vor. Jetzt kann begonnen werde die Rassen zu // vergeheimdiensteln. Ab hier kommt die KI für den Geheimdienst richtig ins Spiel. for (std::map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) { if (it->second->AHumanPlays() == false) { CIntelligence* pIntel = it->second->GetEmpire()->GetIntelligence(); // wenn in den letzten 5 Runden Geheimdienstberichte mit uns als Ziel vorliegen, so wird die innere // Sicherheit maximiert if (badReports[it->first] > NULL) { // Es liegt mindst. ein Bericht mit uns als Ziel aus den letzten 5 Runden vor. // Dann wird die Innere Sicherheit auf 100% gesetzt pIntel->SetAssignment()->SetGlobalPercentage(2, 100, it->second, "", pmMajors); continue; } // wenn die innere Sicherheit nicht verändert werden musste, dann können wir vielleicht selbst aktiv werden // KI benutzt nur Sabotage // Wie wird ein mögliches Geheimdienstopfer ermittelt? // - haben die schlechteste Beziehung zum Opfer // - Beziehung unter 50% oder aktueller Vertrag kleiner Freundschaft und kein Verteidigungsbündnis USHORT worstRel = MAXBYTE; CMajor* pWorstRace = NULL; for (std::map<CString, CMajor*>::const_iterator jt = pmMajors->begin(); jt != pmMajors->end(); ++jt) if (jt->first != it->first && it->second->IsRaceContacted(jt->first) == true) { // zufällig wird hier eine bekannte andere Rasse als ResponsibleRace ausgewählt pIntel->SetResponsibleRace(it->first); // erstmal uns wieder auf die ResponsibleRace setzen if (jt->second->GetEmpire()->CountSystems() > 0 && rand()%3 == NULL) { pIntel->SetResponsibleRace(jt->first); break; } // vertragliche Situation und Mindestbeziehung checken if ((it->second->GetAgreement(jt->first) < DIPLOMATIC_AGREEMENT::FRIENDSHIP && it->second->GetDefencePact(jt->first) == false) || it->second->GetRelation(jt->first) < 50) { // schlechteste Beziehung ermitteln if (it->second->GetRelation(jt->first) < worstRel) { worstRel = it->second->GetRelation(jt->first); pWorstRace = jt->second; } // bei Gleichheit zu 50% die neue Rasse mit schlechtester Bezeihung else if (it->second->GetRelation(jt->first) == worstRel && rand()%2 == NULL) { worstRel = it->second->GetRelation(jt->first); pWorstRace = jt->second; } } } // jetzt der ausgesuchten Rasse Geheimdienstpunkte zuweisen if (pWorstRace != NULL) { CIntelligence* pWorstIntel = pWorstRace->GetEmpire()->GetIntelligence(); MYTRACE("intelai")(MT::LEVEL_INFO, "Intel-AI: assigned intel victim of %s is %s\n", it->first, pWorstRace->GetRaceID()); // jede Rasse läßt immer einen bestimmten prozentualen Anteil in der inneren Sicherheit. int innerSecPerc = 25; if (it->second->IsRaceProperty(RACE_PROPERTY::FINANCIAL)) innerSecPerc += 15; if (it->second->IsRaceProperty(RACE_PROPERTY::WARLIKE)) innerSecPerc += 25; if (it->second->IsRaceProperty(RACE_PROPERTY::AGRARIAN)) innerSecPerc += 25; if (it->second->IsRaceProperty(RACE_PROPERTY::INDUSTRIAL)) innerSecPerc += 10; if (it->second->IsRaceProperty(RACE_PROPERTY::SECRET)) innerSecPerc -= 10; if (it->second->IsRaceProperty(RACE_PROPERTY::SCIENTIFIC)) innerSecPerc += 0; if (it->second->IsRaceProperty(RACE_PROPERTY::PRODUCER)) innerSecPerc += 5; if (it->second->IsRaceProperty(RACE_PROPERTY::PACIFIST)) innerSecPerc += 35; if (it->second->IsRaceProperty(RACE_PROPERTY::SNEAKY)) innerSecPerc -= 15; if (it->second->IsRaceProperty(RACE_PROPERTY::SOLOING)) innerSecPerc += 40; if (it->second->IsRaceProperty(RACE_PROPERTY::HOSTILE)) innerSecPerc += 0; if (innerSecPerc > 100) innerSecPerc = 100; else if (innerSecPerc < 0) innerSecPerc = 0; if (pIntel->GetAssignment()->GetGlobalSabotagePercentage(pWorstRace->GetRaceID()) != 100 - innerSecPerc) pIntel->SetAssignment()->SetGlobalPercentage(2, 100, it->second, "", pmMajors); pIntel->SetAssignment()->SetGlobalPercentage(1, 100 - innerSecPerc, it->second, pWorstRace->GetRaceID(), pmMajors); // Wann wird die Geheimdiensaktion gestartet // - wenn unsere Geheimdienstpunkte + Punkte aus Depot > gegnerische Innere Sicherheit + deren Inneres Depot int type = rand()%4; // Typ der Aktion (Wirtschaft, Wissenschaft, Militär oder Diplomatie) UINT ourPoints = pIntel->GetSecurityPoints() * pIntel->GetAssignment()->GetGlobalSabotagePercentage(pWorstRace->GetRaceID()) / 100 + pIntel->GetSPStorage(1, pWorstRace->GetRaceID()) * pIntel->GetAssignment()->GetSabotagePercentages(pWorstRace->GetRaceID(), type) / 100; ourPoints += ourPoints * pIntel->GetBonus(type, 1) / 100; UINT enemyPoints = pWorstIntel->GetSecurityPoints() * pWorstIntel->GetAssignment()->GetInnerSecurityPercentage() / 100; // + Bonus auf innere Sicherheit enemyPoints += enemyPoints * pWorstIntel->GetInnerSecurityBoni() / 100; // + Punkte aus dem Lager (darin ist der Bonus schon vorhanden) enemyPoints += pWorstIntel->GetInnerSecurityStorage(); if (ourPoints > enemyPoints + rand()%1500) { // zuerst komplette Zuteilung ins Lager übernehmen, damit man dann auch wirklich 100% einem einzelnen // Ressort zuweisen kann pIntel->SetAssignment()->SetSabotagePercentage(4, 100, pWorstRace->GetRaceID()); pIntel->SetAssignment()->SetSabotagePercentage(type, 100, pWorstRace->GetRaceID()); } else pIntel->SetAssignment()->SetSabotagePercentage(4, 100, pWorstRace->GetRaceID()); MYTRACE("intelai")(MT::LEVEL_INFO, "Intel-AI: our SP: %d - enemies SP: %d\n", ourPoints, enemyPoints); } // finden wir keine Rasse zum vergeheimdiensteln, so die innere Sicherheit auf 100% stellen else pIntel->SetAssignment()->SetGlobalPercentage(2, 100, it->second, "", pmMajors); } } }
void CShipDesignMenuView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CBotEDoc* pDoc = resources::pDoc; ASSERT(pDoc); if (!pDoc->m_bDataReceived) return; CMajor* pMajor = m_pPlayersRace; ASSERT(pMajor); if (!pMajor) return; // clicked to DisplayAllShips CRect rect; rect.SetRect(40,750,80,30); if (rect.PtInRect(point)) { AfxMessageBox("Button DisplayAllShips pressed"); m_bDisplayAllShips=!m_bDisplayAllShips; AfxMessageBox("Button DisplayAllShips pressed2"); //if (m_bDisplayAllShips) // std::sort(m_vRaceList.begin(), m_vRaceList.end(),ComareRaceAgreement); //else // std::sort(m_vRaceList.begin(), m_vRaceList.end(),CompareRaceName); Invalidate(); return; } CalcLogicalPoint(point); // Wenn wir in der Schiffsdesignansicht sind CRect r; r.SetRect(0,0,m_TotalSize.cx,m_TotalSize.cy); // Schiffsinfoarray durchgehen und nach zum Imperium gehörende baubare Schiffe suchen short j = 0; short counter = m_iClickedOnShip - 23 + m_iOldClickedOnShip; short add = 0; BYTE researchLevels[6] = { pMajor->GetEmpire()->GetResearch()->GetBioTech(), pMajor->GetEmpire()->GetResearch()->GetEnergyTech(), pMajor->GetEmpire()->GetResearch()->GetCompTech(), pMajor->GetEmpire()->GetResearch()->GetPropulsionTech(), pMajor->GetEmpire()->GetResearch()->GetConstructionTech(), pMajor->GetEmpire()->GetResearch()->GetWeaponTech() }; for (int i = 0; i < pDoc->m_ShipInfoArray.GetSize(); i++) if (pDoc->m_ShipInfoArray.GetAt(i).GetRace() == pMajor->GetRaceShipNumber()) if (!pDoc->m_ShipInfoArray.GetAt(i).IsStation()) if (pDoc->m_ShipInfoArray.GetAt(i).IsThisShipBuildableNow(researchLevels)) { // wurde dieses Schiff durch kein anderes jetzt baubares Schiff schon obsolet? BOOLEAN foundObsolet = FALSE; for (int m = 0; m < pDoc->m_ShipInfoArray.GetSize(); m++) if (pDoc->m_ShipInfoArray.GetAt(m).GetRace() == pMajor->GetRaceShipNumber()) if (pDoc->m_ShipInfoArray.GetAt(m).GetObsoleteShipClass() == pDoc->m_ShipInfoArray.GetAt(i).GetShipClass()) if (pDoc->m_ShipInfoArray.GetAt(m).IsThisShipBuildableNow(researchLevels)) { foundObsolet = TRUE; break; } if (foundObsolet) continue; if (counter > 0) { add++; counter--; continue; } if (j < 24) { // Müssen später noch die Seitenzahl beachten, bis jetzt aber wie in der Diplomatieansicht // geht die Liste nur auf eine Seite if (CRect(20,120+j*25,200,145+j*25).PtInRect(point)) { m_iClickedOnShip = j + add; m_iOldClickedOnShip = 23-(j)%24; m_iBeamWeaponNumber = 0; m_iTorpedoWeaponNumber = 0; m_bFoundBetterBeam = FALSE; m_bFoundWorseBeam = FALSE; Invalidate(); return; } if (j + add == m_iClickedOnShip) m_pShownShip = &pDoc->m_ShipInfoArray.GetAt(i); j++; } } if (m_bDisplayAllShips) { Invalidate(FALSE); return; } // Bevor wir irgendetwas ändern können müssen wir überprüfen, dass das gerade angeklickte Schiff nicht gerade // gebaut wird. Wenn das der Fall sein sollte können wir nix ändern. Es kommt dann eine Meldung in welchem // System das Schiff gerade gebaut wird if (CRect(r.right-300,80,r.right,r.bottom-80).PtInRect(point)) if (!CheckIfShipIsBuilding(m_pShownShip).IsEmpty()) { Invalidate(FALSE); return; } counter = 0; // Überprüfen ob irgendetwas an den Beamwaffen ändern möchte if (m_pShownShip && m_pShownShip->GetBeamWeapons()->GetSize() > 0) { // Hat das Schiff mehr als eine Beamwaffe können wir auf die nächste zugreifen indem wir hier klicken if (CRect(r.right-300,80,r.right,105).PtInRect(point)) { if (m_pShownShip->GetBeamWeapons()->GetUpperBound() > m_iBeamWeaponNumber) { m_iBeamWeaponNumber++; m_bFoundBetterBeam = FALSE; m_bFoundWorseBeam = FALSE; Invalidate(); } else if (m_pShownShip->GetBeamWeapons()->GetUpperBound() == m_iBeamWeaponNumber) { m_iBeamWeaponNumber = 0; m_bFoundBetterBeam = FALSE; m_bFoundWorseBeam = FALSE; Invalidate(); } } // Haben wir auf den Button geklickt um den Typ der Beamwaffe zu verbessern else if (m_bFoundBetterBeam == TRUE && CRect(r.right-145,120,r.right-25,150).PtInRect(point)) { // Dann wird der Typ bei der aktuellen Beamwaffe um eins erhöht CBeamWeapons* pWeapon = &m_pShownShip->GetBeamWeapons()->GetAt(m_iBeamWeaponNumber); BYTE oldType = pWeapon->GetBeamType(); USHORT oldPower = pWeapon->GetBeamPower(); BYTE oldNumber = pWeapon->GetBeamNumber(); BYTE oldShootNumber = pWeapon->GetShootNumber(); CString oldName = pWeapon->GetBeamName(); BYTE oldBonus = pWeapon->GetBonus(); BYTE oldLenght = pWeapon->GetBeamLenght(); BYTE oldRechargeTime= pWeapon->GetRechargeTime(); BOOLEAN piercing = pWeapon->GetPiercing(); BOOLEAN modulating = pWeapon->GetModulating(); // hier aktualisieren -> Reichweite erhöhen pWeapon->ModifyBeamWeapon((oldType+1),oldPower,oldNumber,oldName,modulating,piercing,oldBonus,oldLenght,oldRechargeTime,oldShootNumber); // Feuerwinkel bleiben alle beim alten m_pShownShip->CalculateFinalCosts(); m_bFoundBetterBeam = FALSE; m_bFoundWorseBeam = FALSE; Invalidate(); } // Haben wir auf den Button geklickt um den Typ der Beamwaffe zu verringern else if (m_bFoundWorseBeam == TRUE && CRect(r.right-275,120,r.right-155,150).PtInRect(point)) { // Dann wird der Typ bei der aktuellen Beamwaffe um eins erhöht CBeamWeapons* pWeapon = &m_pShownShip->GetBeamWeapons()->GetAt(m_iBeamWeaponNumber); BYTE oldType = pWeapon->GetBeamType(); USHORT oldPower = pWeapon->GetBeamPower(); BYTE oldNumber = pWeapon->GetBeamNumber(); BYTE oldShootNumber = pWeapon->GetShootNumber(); CString oldName = pWeapon->GetBeamName(); BYTE oldBonus = pWeapon->GetBonus(); BYTE oldLenght = pWeapon->GetBeamLenght(); BYTE oldRechargeTime= pWeapon->GetRechargeTime(); BOOLEAN piercing = pWeapon->GetPiercing(); BOOLEAN modulating = pWeapon->GetModulating(); // hier aktualisieren -> Reichweite erhöhen pWeapon->ModifyBeamWeapon((oldType-1),oldPower,oldNumber,oldName,modulating,piercing,oldBonus,oldLenght,oldRechargeTime,oldShootNumber); // Feuerwinkel bleiben alle beim alten m_pShownShip->CalculateFinalCosts(); m_bFoundBetterBeam = FALSE; m_bFoundWorseBeam = FALSE; Invalidate(); } } counter++; // Überprüfen ob wir irgendetwas an einer Torpedowaffe ändern möchten if (m_pShownShip && m_pShownShip->GetTorpedoWeapons()->GetSize() > 0) { // Hat das Schiff mehr als eine Torpedowaffe können wir auf die nächste zugreifen indem wir hier klicken if (CRect(r.right-300,80+counter*90,r.right,125+counter*90).PtInRect(point)) { if (m_pShownShip->GetTorpedoWeapons()->GetUpperBound() > m_iTorpedoWeaponNumber) { m_iTorpedoWeaponNumber++; Invalidate(); } else if (m_pShownShip->GetTorpedoWeapons()->GetUpperBound() == m_iTorpedoWeaponNumber) { m_iTorpedoWeaponNumber = 0; Invalidate(); } } // Haben wir auf den Button geklickt um den Torpedowerfer zu ändern else if (CRect(r.right-275,140+counter*90,r.right-145,170+counter*90).PtInRect(point)) { CTorpedoWeapons* pWeapon = &m_pShownShip->GetTorpedoWeapons()->GetAt(m_iTorpedoWeaponNumber); BYTE oldTorpType = pWeapon->GetTorpedoType(); BYTE oldTupeNumber = pWeapon->GetNumberOfTupes(); BYTE oldAcc = pWeapon->GetAccuracy(); CString oldTupeName = pWeapon->GetTupeName(); TupeWeaponsObserverStruct twos = pMajor->GetWeaponObserver()->GetNextTupe(oldTupeName,oldTorpType); // hier aktualisieren pWeapon->ModifyTorpedoWeapon(oldTorpType,twos.number,twos.fireRate,oldTupeNumber,twos.TupeName,twos.onlyMicro,oldAcc); USHORT nMountPos = pWeapon->GetFirearc()->GetPosition(); USHORT nAngle = twos.fireAngle; pWeapon->GetFirearc()->SetValues(nMountPos, nAngle); m_pShownShip->CalculateFinalCosts(); Invalidate(); } // Haben wir auf den Button geklickt um den Torpedotyp zu ändern else if (CRect(r.right-145,140+counter*90,r.right-25,170+counter*90).PtInRect(point)) { CTorpedoWeapons* pWeapon = &m_pShownShip->GetTorpedoWeapons()->GetAt(m_iTorpedoWeaponNumber); BYTE oldNumber = pWeapon->GetNumber(); BYTE oldFirerate = pWeapon->GetTupeFirerate(); BYTE oldTupeNumber = pWeapon->GetNumberOfTupes(); BOOLEAN oldOnlyMicro= pWeapon->GetOnlyMicroPhoton(); BYTE oldAcc = pWeapon->GetAccuracy(); BYTE oldTorpType = pWeapon->GetTorpedoType(); CString oldTupeName = pWeapon->GetTupeName(); BYTE newTorpType = pMajor->GetWeaponObserver()->GetNextTorpedo(oldTorpType, oldOnlyMicro); // hier aktualisieren pWeapon->ModifyTorpedoWeapon(newTorpType,oldNumber,oldFirerate,oldTupeNumber,oldTupeName,oldOnlyMicro,oldAcc); // Feuerwinkel bleiben gleich m_pShownShip->CalculateFinalCosts(); Invalidate(); } } counter++; // Überprüfen ob wir das Hüllenmaterial ändern möchten, also ob wir auf den Button "Hüllenmaterial ändern" geklickt haben if (m_pShownShip && CRect(r.right-275,180+counter*120,r.right-155,210+counter*120).PtInRect(point)) { CHull* pHull = m_pShownShip->GetHull(); BOOLEAN oldDoubleHull = pHull->GetDoubleHull(); ULONG oldBaseHull = pHull->GetBaseHull(); BOOLEAN ablative = pHull->GetAblative(); BOOLEAN polarisation = pHull->GetPolarisation(); // Dann bekommt das nächste Schiff ein neues Hüllenmaterial switch (pHull->GetHullMaterial()) { case TITAN: pHull->ModifyHull(oldDoubleHull,oldBaseHull,DURANIUM,ablative,polarisation); break; case DURANIUM: pHull->ModifyHull(oldDoubleHull,oldBaseHull,IRIDIUM,ablative,polarisation); break; case IRIDIUM: pHull->ModifyHull(oldDoubleHull,oldBaseHull,TITAN,ablative,polarisation); break; } m_pShownShip->CalculateFinalCosts(); Invalidate(); } // Überprüfen ob wir geklickt haben um die Hüllenart zu wechseln (also Einzel- oder Doppelhülle) else if (m_pShownShip && CRect(r.right-145,180+counter*120,r.right-25,210+counter*120).PtInRect(point)) { CHull* pHull = m_pShownShip->GetHull(); BOOLEAN oldDoubleHull = pHull->GetDoubleHull(); // wenn eine Doppelhülle draus gemacht werden soll dann darf die Manövrierbarkeit nicht schon "keine" oder nur 1 sein if (oldDoubleHull == FALSE && m_pShownShip->GetManeuverability() <= 1) return; // wenn eine Einzelhülle draus gemacht werden soll, dann darf die Manövrierbarkeit nicht schon phänomenal sein if (oldDoubleHull == TRUE && m_pShownShip->GetManeuverability() == 9) return; // Wenn die alte Hülle eine Einzelhülle war und man eine Doppelhülle anbaut, dann verringert sich die // Manövriebarkeit um -1. Wenn man eine Einzelhülle anbaut, dann kommt zur Manö +1 dazu. Schiffe mit // Manö 0 oder Manö 9 sind von dieser Reglung ausgeschlossen. if (m_pShownShip->GetManeuverability() >= 0 && m_pShownShip->GetManeuverability() <= 9) { // wollen Doppelhülle draus machen if (oldDoubleHull == FALSE) m_pShownShip->SetManeuverability(m_pShownShip->GetManeuverability()-1); // wollen eine Einzelhülle draus machen else m_pShownShip->SetManeuverability(m_pShownShip->GetManeuverability()+1); } BOOLEAN ablative = pHull->GetAblative(); BOOLEAN polarisation = pHull->GetPolarisation(); ULONG oldBaseHull = pHull->GetBaseHull(); BYTE oldHullMaterial = pHull->GetHullMaterial(); pHull->ModifyHull(!oldDoubleHull,oldBaseHull,oldHullMaterial,ablative,polarisation); m_pShownShip->CalculateFinalCosts(); Invalidate(); } // Überprüfen ob ich geklickt habe um den Schildtyp zu verringern else if (m_pShownShip && CRect(r.right-275,300+counter*120,r.right-155,325+counter*120).PtInRect(point)) { if (m_pShownShip->GetShield()->GetShieldType() > 0) { CShield* pShield = m_pShownShip->GetShield(); UINT oldMaxShield = pShield->GetMaxShield(); BYTE oldShieldType = pShield->GetShieldType(); BOOLEAN regenerative= pShield->GetRegenerative(); pShield->ModifyShield(oldMaxShield, (oldShieldType - 1), regenerative); m_pShownShip->CalculateFinalCosts(); Invalidate(); } } // Überprüfen ob ich geklickt habe um den Schildtyp zu erhöhen else if (m_pShownShip && CRect(r.right-145,300+counter*120,r.right-25,325+counter*120).PtInRect(point)) { CShield* pShield = m_pShownShip->GetShield(); USHORT oldShieldType = pShield->GetShieldType(); if (pMajor->GetWeaponObserver()->GetMaxShieldType() > oldShieldType) { UINT oldMaxShield = pShield->GetMaxShield(); BOOLEAN regenerative= pShield->GetRegenerative(); pShield->ModifyShield(oldMaxShield, (oldShieldType + 1), regenerative); m_pShownShip->CalculateFinalCosts(); Invalidate(); } } CMainBaseView::OnLButtonDown(nFlags, point); }
///////////////////////////////////////////////////////////////////////////////////////// // Hier die Funktion zum Zeichnen des Schiffsdesignmenüs ///////////////////////////////////////////////////////////////////////////////////////// void CShipDesignMenuView::DrawShipDesignMenue(Graphics* g) { CBotEDoc* pDoc = resources::pDoc; ASSERT(pDoc); CMajor* pMajor = m_pPlayersRace; ASSERT(pDoc); if (!pMajor) return; CString fontName = ""; Gdiplus::REAL fontSize = 0.0; // Rassenspezifische Schriftart auswählen CFontLoader::CreateGDIFont(pMajor, 2, fontName, fontSize); // Schriftfarbe wählen Gdiplus::Color normalColor; CFontLoader::GetGDIFontColor(pMajor, 3, normalColor); StringFormat fontFormat; fontFormat.SetAlignment(StringAlignmentNear); fontFormat.SetLineAlignment(StringAlignmentCenter); fontFormat.SetFormatFlags(StringFormatFlagsNoWrap); Color penColor; penColor.SetFromCOLORREF(pMajor->GetDesign()->m_clrListMarkPenColor); Color markColor; markColor.SetFromCOLORREF(pMajor->GetDesign()->m_clrListMarkTextColor); if (bg_designmenu) g->DrawImage(bg_designmenu, 0, 0, 1075, 750); SolidBrush fontBrush(normalColor); // Links im Bild die veränderbaren Schiffklassen zeichnen (bis jetzt darf man keine Stationen verändern, // weil deren Baukosten allein von den Industriekosten berechnet werden. Diese aber nicht steigen wenn // man die Hülle oder Schilde verbessert. Somit könnte man bessere Stationen für den gleichen Preis bauen. // Schiffsinfoarray durchgehen und nach zum Imperium gehörende baubare Schiffe suchen short j = 0; short counter = m_iClickedOnShip - 23 + m_iOldClickedOnShip; short oldClickedShip = m_iClickedOnShip; BYTE researchLevels[6] = { pMajor->GetEmpire()->GetResearch()->GetBioTech(), pMajor->GetEmpire()->GetResearch()->GetEnergyTech(), pMajor->GetEmpire()->GetResearch()->GetCompTech(), pMajor->GetEmpire()->GetResearch()->GetPropulsionTech(), pMajor->GetEmpire()->GetResearch()->GetConstructionTech(), pMajor->GetEmpire()->GetResearch()->GetWeaponTech() }; m_pShownShip = NULL; m_nSizeOfShipDesignList = 0; // Es gehen nur 21 Einträge auf die Seite, deshalb muss abgebrochen werden for (int i = 0; i < pDoc->m_ShipInfoArray.GetSize(); i++) if (pDoc->m_ShipInfoArray.GetAt(i).GetRace() == pMajor->GetRaceShipNumber()) if (!pDoc->m_ShipInfoArray.GetAt(i).IsStation()) if (pDoc->m_ShipInfoArray.GetAt(i).IsThisShipBuildableNow(researchLevels)) { // wurde dieses Schiff durch kein anderes jetzt baubares Schiff schon obsolet? BOOLEAN foundObsolet = FALSE; for (int m = 0; m < pDoc->m_ShipInfoArray.GetSize(); m++) if (pDoc->m_ShipInfoArray.GetAt(m).GetRace() == pMajor->GetRaceShipNumber()) if (pDoc->m_ShipInfoArray.GetAt(m).GetObsoleteShipClass() == pDoc->m_ShipInfoArray.GetAt(i).GetShipClass()) if (pDoc->m_ShipInfoArray.GetAt(m).IsThisShipBuildableNow(researchLevels)) { foundObsolet = TRUE; break; } if (foundObsolet) continue; m_nSizeOfShipDesignList++; if (counter > 0) { m_iClickedOnShip--; counter--; continue; } if (j < 24) { fontBrush.SetColor(normalColor); // Wenn wir ein Schiff gefunden haben, dann zeichnen wir dieses in die Liste (max. 21) // Wenn wir das Schiff markiert haben, dann die Markierung zeichnen, haben wir kein spezielles Schiff // angeklickt, so wird das 1. Schiff in der Liste markiert if (j == m_iClickedOnShip || m_iClickedOnShip == -1) { fontBrush.SetColor(markColor); // Wenn wir nix angeklickt haben und nur das erste Schiff markiert war, dann automatisch m_iClickedOnShip = j; if (oldClickedShip == -1) oldClickedShip = j; m_pShownShip = &pDoc->m_ShipInfoArray.GetAt(i); // Markierung worauf wir geklickt haben g->FillRectangle(&SolidBrush(Color(50,200,200,200)), RectF(15,120+j*25,183,25)); g->DrawLine(&Gdiplus::Pen(penColor), 15, 120+j*25, 198, 120+j*25); g->DrawLine(&Gdiplus::Pen(penColor), 15, 145+j*25, 198, 145+j*25); // Infos in unteren Schiffsdesignansicht aktualisieren if (CShipDesignBottomView* pView = dynamic_cast<CShipDesignBottomView*>(resources::pMainFrame->GetView(RUNTIME_CLASS(CShipDesignBottomView)))) { if (pView->GetCurrentShipInfo() != i) { pView->SetCurrentShipInfo(i); pView->Invalidate(FALSE); } } } CString s = pDoc->m_ShipInfoArray.GetAt(i).GetShipClass(); g->DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(25, 120 + j * 25, 175, 25), &fontFormat, &fontBrush); j++; } } m_iClickedOnShip = oldClickedShip; // Hier jetzt Informationen zum angeklickten Schiff anzeigen if (m_pShownShip) { // Bild des Schiffes zeichnen CString s; s.Format("Ships\\%s.bop",m_pShownShip->GetShipClass()); Bitmap* graphic = pDoc->GetGraphicPool()->GetGDIGraphic(s); if (graphic == NULL) graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Ships\\ImageMissing.bop"); if (graphic) { g->DrawImage(graphic, 388, 90, 200, 150); graphic = NULL; } // allgemeine Schiffsinformationen anzeigen m_pShownShip->DrawShipInformation(g, CRect(220,250,740,440), &Gdiplus::Font(CComBSTR(fontName), fontSize), normalColor, markColor, pMajor->GetEmpire()->GetResearch()); // Baukosten des Schiffes anzeigen fontBrush.SetColor(markColor); fontFormat.SetAlignment(StringAlignmentCenter); fontFormat.SetLineAlignment(StringAlignmentNear); g->DrawString(CComBSTR(CLoc::GetString("BUILDCOSTS")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(190,440,580,25), &fontFormat, &fontBrush); fontBrush.SetColor(normalColor); s.Format("%s: %d %s: %d %s: %d",CLoc::GetString("INDUSTRY"),m_pShownShip->GetNeededIndustry(), CLoc::GetString("TITAN"),m_pShownShip->GetNeededTitan(), CLoc::GetString("DEUTERIUM"),m_pShownShip->GetNeededDeuterium()); g->DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(190,465,580,25), &fontFormat, &fontBrush); s.Format("%s: %d %s: %d %s: %d %s: %d",CLoc::GetString("DURANIUM"),m_pShownShip->GetNeededDuranium(), CLoc::GetString("CRYSTAL"),m_pShownShip->GetNeededCrystal(), CLoc::GetString("IRIDIUM"),m_pShownShip->GetNeededIridium(), CLoc::GetString("DERITIUM"),m_pShownShip->GetNeededDeritium()); g->DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(190,490,580,25), &fontFormat, &fontBrush); // Die Buttons zur Eigenschaftsänderung in der Rechten Seite der Ansicht anzeigen // zuerst überprüfen wir die Beamwaffen, wir können den Typ der Beamwaffe verändern, wenn wir mindst. ein anderes // Schiff des Imperiums finden, welches DIESE Beamwaffe mit einem höheren Typ oder einem niedrigeren Typ besitzt graphic = pDoc->GetGraphicPool()->GetGDIGraphic("Other\\" + pMajor->GetPrefix() + "button_small.bop"); Color btnColor; CFontLoader::GetGDIFontColor(pMajor, 1, btnColor); SolidBrush btnBrush(btnColor); fontFormat.SetAlignment(StringAlignmentCenter); fontFormat.SetLineAlignment(StringAlignmentCenter); // Nach Beamwaffen suchen if (m_pShownShip->GetBeamWeapons()->GetSize() > m_iBeamWeaponNumber) { // gibt es schon von dieser Beamwaffe hier auf dem Schiff einen höheren Typ? USHORT maxTyp = pMajor->GetWeaponObserver()->GetMaxBeamType(m_pShownShip->GetBeamWeapons()->GetAt(m_iBeamWeaponNumber).GetBeamName()); if (maxTyp > m_pShownShip->GetBeamWeapons()->GetAt(m_iBeamWeaponNumber).GetBeamType()) { // Dann können wir den Typ unserer Beamwaffe(n) verbessern if (graphic) g->DrawImage(graphic, 930, 120, 120, 30); g->DrawString(CComBSTR(CLoc::GetString("BTN_STRONGER")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(930,120,120,30), &fontFormat, &btnBrush); m_bFoundBetterBeam = TRUE; } // Wenn wir einen größeren Typ als Typ 1 haben, dann können wir diesen verringern if (m_pShownShip->GetBeamWeapons()->GetAt(m_iBeamWeaponNumber).GetBeamType() > 1) { // Dann können wir den Typ unserer Beamwaffe(n) verkleinern if (graphic) g->DrawImage(graphic, 800, 120, 120, 30); g->DrawString(CComBSTR(CLoc::GetString("BTN_WEAKER")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(800,120,120,30), &fontFormat, &btnBrush); m_bFoundWorseBeam = TRUE; } // Typ und Name der Beamwaffe zeichnen fontBrush.SetColor(normalColor); s.Format("%s %d %s",CLoc::GetString("TYPE"),m_pShownShip->GetBeamWeapons()->GetAt(m_iBeamWeaponNumber).GetBeamType(),m_pShownShip->GetBeamWeapons()->GetAt(m_iBeamWeaponNumber).GetBeamName()); fontFormat.SetTrimming(StringTrimmingEllipsisCharacter); g->DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(845,80,160,25), &fontFormat, &fontBrush); fontFormat.SetTrimming(StringTrimmingNone); } // Nach anderer Torpedowaffe suchen if (m_pShownShip->GetTorpedoWeapons()->GetSize() > m_iTorpedoWeaponNumber) { // den aktuellen Torpedotyp holen BYTE currentTorpType = m_pShownShip->GetTorpedoWeapons()->GetAt(m_iTorpedoWeaponNumber).GetTorpedoType(); // Torpedoname zeichnen fontBrush.SetColor(normalColor); s.Format("%s (%d°)",m_pShownShip->GetTorpedoWeapons()->GetAt(m_iTorpedoWeaponNumber).GetTupeName(), m_pShownShip->GetTorpedoWeapons()->GetAt(m_iTorpedoWeaponNumber).GetFirearc()->GetAngle()); g->DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(775,170,300,25), &fontFormat, &fontBrush); s.Format("%s (%d)", CTorpedoInfo::GetName(currentTorpType), CTorpedoInfo::GetPower(currentTorpType)); g->DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(775,195,300,25), &fontFormat, &fontBrush); if (graphic) g->DrawImage(graphic, 800, 230, 120, 30); g->DrawString(CComBSTR(CLoc::GetString("BTN_LAUNCHER")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(800,230,120,30), &fontFormat, &btnBrush); if (graphic) g->DrawImage(graphic, 930, 230, 120, 30); g->DrawString(CComBSTR(CLoc::GetString("BTN_TORPEDO")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(930,230,120,30), &fontFormat, &btnBrush); } // hier Möglichkeit anderes Hüllenmaterial anzubringen eingebaut CString material; switch (m_pShownShip->GetHull()->GetHullMaterial()) { case TITAN: material = CLoc::GetString("TITAN");; break; case DURANIUM: material = CLoc::GetString("DURANIUM");; break; case IRIDIUM: material = CLoc::GetString("IRIDIUM");; break; default: material = ""; } BOOLEAN bDoubleHull = m_pShownShip->GetHull()->GetDoubleHull(); if (bDoubleHull == TRUE) s.Format("%s%s",material, CLoc::GetString("DOUBLE_HULL_ARMOUR")); else s.Format("%s%s",material, CLoc::GetString("HULL_ARMOR")); g->DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(775,380,300,30), &fontFormat, &fontBrush); // Hier kann man den Schildtyp ändern // zuerst Anzeige der jetzt aktuellen Schilde. Beim Romulaner eine schwarze Schriftart wählen. Wenn dies // später auch bei der Föd heller unterlegt ist kann auch dort eine schwarze Schriftfarbe gewählt werden. s.Format("%s %d %s",CLoc::GetString("TYPE"),m_pShownShip->GetShield()->GetShieldType(),CLoc::GetString("SHIELDS")); g->DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(775,490,300,30), &fontFormat, &fontBrush); // Ab jetzt die Buttons zum Ändern der jeweiligen Komponenten if (graphic) g->DrawImage(graphic, 800, 420, 120, 30); g->DrawString(CComBSTR(CLoc::GetString("BTN_MATERIAL")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(800,420,120,30), &fontFormat, &btnBrush); // wenn eine Doppelhülle draus gemacht werden soll dann darf die Manövrierbarkeit nicht schon "keine" oder nur 1 sein // wenn eine Einzelhülle draus gemacht werden soll, dann darf die Manövrierbarkeit nicht schon phänomenal sein if ((bDoubleHull == FALSE && m_pShownShip->GetManeuverability() > 1) || (bDoubleHull == TRUE && m_pShownShip->GetManeuverability() < 9)) { if (graphic) g->DrawImage(graphic, 930, 420, 120, 30); g->DrawString(CComBSTR(CLoc::GetString("BTN_HULLTYPE")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(930,420,120,30), &fontFormat, &btnBrush); } // Schildtyp schwächer Button einblenden if (m_pShownShip->GetShield()->GetShieldType() > 0) { if (graphic) g->DrawImage(graphic, 800, 540, 120, 30); g->DrawString(CComBSTR(CLoc::GetString("BTN_WEAKER")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(800,540,120,30), &fontFormat, &btnBrush); } // Schildtyp stärker Button einblenden if (m_pShownShip->GetShield()->GetShieldType() < pMajor->GetWeaponObserver()->GetMaxShieldType()) { if (graphic) g->DrawImage(graphic, 930, 540, 120, 30); g->DrawString(CComBSTR(CLoc::GetString("BTN_STRONGER")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(930,540,120,30), &fontFormat, &btnBrush); } } // Wenn das Schiff in irgendeinem unserer Systeme gebaut wird, dann großen Text ausgeben, in welchem System das Schiff // gerade gebaut wird CString systemName = CheckIfShipIsBuilding(m_pShownShip); if (!systemName.IsEmpty()) { COverlayBanner *banner = new COverlayBanner(CPoint(200,300), CSize(580, 200), CLoc::GetString("NO_CHANGE_POSSIBLE", FALSE, systemName), RGB(220,0,0)); banner->Draw(g, &Gdiplus::Font(CComBSTR(fontName), fontSize)); delete banner; } // draw Button DisplayAllShips Bitmap* btnDisplayAllShips = pDoc->GetGraphicPool()->GetGDIGraphic("Other\\" + pMajor->GetPrefix() + "button_small.bop");//All-Button zeichnen if(btnDisplayAllShips) g->DrawImage(btnDisplayAllShips,40,750,80,30); CString s; //AfxMessageBox("m_bDisplayAllShips"); if (m_bDisplayAllShips) s=CLoc::GetString("BTN_ALL"); else s=CLoc::GetString("BTN_CURRENTS"); g->DrawString(CComBSTR(s), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(40,750,80,30), &fontFormat, &fontBrush); // "Schiffsdesign" in der Mitte zeichnen // Rassenspezifische Schriftart auswählen CFontLoader::CreateGDIFont(pMajor, 5, fontName, fontSize); // Schriftfarbe wählen CFontLoader::GetGDIFontColor(pMajor, 3, normalColor); fontBrush.SetColor(normalColor); g->DrawString(CComBSTR(CLoc::GetString("SHIPDESIGN")), -1, &Gdiplus::Font(CComBSTR(fontName), fontSize), RectF(188,10,600,50), &fontFormat, &fontBrush); }
void CResearchAI::Calc(CBotEDoc* pDoc) { ASSERT(pDoc); // Forschungsdurchschnitt aller Rassen berechnen map<CString, CMajor*>* pmMajors = pDoc->GetRaceCtrl()->GetMajors(); ASSERT(pmMajors); // Map mit zum Major zugehörigen Techlevel map<CMajor*, double> mTechLevels; list<double> lTechLevels; for (map<CString, CMajor*>::const_iterator it = pmMajors->begin(); it != pmMajors->end(); ++it) { CMajor* pMajor = it->second; // für menschliche Spieler wird die KI nichts tun if (!pMajor || pMajor->AHumanPlays()) continue; double dTechLevel = pMajor->GetEmpire()->GetResearch()->GetBioTech() + pMajor->GetEmpire()->GetResearch()->GetEnergyTech() + pMajor->GetEmpire()->GetResearch()->GetCompTech() + pMajor->GetEmpire()->GetResearch()->GetPropulsionTech() + pMajor->GetEmpire()->GetResearch()->GetConstructionTech() + pMajor->GetEmpire()->GetResearch()->GetWeaponTech(); dTechLevel /= 6.0; lTechLevels.push_back(dTechLevel); // Hat die Rasse überhaupt eine Spezialforschung zur Auswahl? (auf FALSE prüfen!) if (!pMajor->GetEmpire()->GetResearch()->GetUniqueReady()) // Hat die Rasse noch keinen Bereich gewählt? if (pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetChoiceTaken() == false) mTechLevels[pMajor] = dTechLevel; } // absteigend sortieren lTechLevels.sort(); lTechLevels.reverse(); // auf die besten zwei begrenzen lTechLevels.resize(2); // nur die Majors mit dem besten oder zweitbesten Techlevel versuchen eine Spezialforschung // zu beginnen. Dies machen sie aber nur, wenn sie mindestens eine Techstufe weiter sind, als // sie für die Spezialforschung benötigt haben for (list<double>::const_iterator it = lTechLevels.begin(); it != lTechLevels.end(); ++it) { // Major mit diesem Techlevel suchen for (map<CMajor*, double>::const_iterator it2 = mTechLevels.begin(); it2 != mTechLevels.end(); ++it2) { if (*it == it2->second) { CMajor* pMajor = it2->first; if (pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetChoiceTaken()) break; BYTE nUniqueTech = pMajor->GetEmpire()->GetResearch()->GetUniqueTech() + 1; // Prüfen ob die Rasse schon ein Level weiter ist, als das was sie für die Spezialforschung braucht if (nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetBioTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetEnergyTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetCompTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetConstructionTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetPropulsionTech() && nUniqueTech < pMajor->GetEmpire()->GetResearch()->GetWeaponTech()) { // zufällig einen Bereich wählen (1 bis 3) int nComplex = rand()%3 + 1; pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->SetUniqueResearchChoosePossibility(nComplex); // 100% zuteilen pMajor->GetEmpire()->GetResearch()->SetPercentage(6, 100); CString sName = pMajor->GetEmpire()->GetResearch()->GetResearchInfo()->GetCurrentResearchComplex()->GetComplexName(); MYTRACE("general")(MT::LEVEL_INFO, "CResearchAI::Calc(): %s choose in unique complex '%s' field %d and set level to 100%%\n", pMajor->GetRaceID(), sName, nComplex); } } } } }