/** ******************************************************************************* @file /gui/model/guiBuilding.cpp @brief Predchudce pro vsechny stavby Makro DEBUG_DRAW_GATES aktivuje vykreslovani trasy kolem budov. Makro DEBUG_DRAW_ATTACKPOSITIONS aktivuje vykreslovat utocne pozice. @author Vajicek @version 0.1 ******************************************************************************/ // #include "gui/model/guiBuilding.h" #include "gui/model/guiUnit.h" #include "gui/model/reader_ase.h" #include "gui/model/guimap.h" #include "gui/common/colors.h" #include "gui/common/Defs.h" #include "gui/common/mymath_ext.h" // #include "common/Log.h" #include "common/compatibility.h" #include using namespace std; // vypnout varovani pri prekladu #pragma warning( disable : 4355 ) namespace gui{ using namespace World; /*TSceneBuildingObject********************************************************/ TSceneBuildingObject::TSceneBuildingObject(gui::TBuilding* build, TModel *mid) :TModelSceneObject(mid) #ifdef DRAW_BUILDING_SHADOWS , TSimpleShadow(this, RASTER_SHADOW) #endif { building = build; iPriorityOfSelection = 5; if(build->iDummy){ selectable = false; transparent = true; } } TMeshNode* TSceneBuildingObject::getCheckPoint(char* name){ return FindMeshNode(inst, name); } int TSceneBuildingObject::getStoredVertexes(char* name, TVertex** verts){ TMeshNode* parea = FindMeshNode(inst, name); *verts = NULL; if(!parea)return 0; T3DObject* obj = parea->obj; TMesh* mesh = obj->mesh + parea->mesh; // int f = obj->poly[mesh->first].first; int l = obj->poly[mesh->last].last; // *verts = obj->vert + f; return l-f+1; } void TSceneBuildingObject::positionUpdated(){ TModelSceneObject::positionUpdated(); InverseMX4( inverse, mx4Pos ); } void TSceneBuildingObject::onClick(){ building->onClick(); } void TSceneBuildingObject::onMouseOver(){ if(building) building->onMouseOver(); } void TSceneBuildingObject::drawObject(){ //nevykreslovat pokud neni videt if(building->fTransparency==0)return; #ifdef DRAW_BUILDING_SHADOWS if (getRealFade() < 3 && !building->iDummy ) drawShadow(); #endif //nastavit viditelnost a barvu float mat1[] = {ColorPlayer[ building->guibiInfo.player ][0]/255.0f, ColorPlayer[ building->guibiInfo.player ][1]/255.0f, ColorPlayer[ building->guibiInfo.player ][2]/255.0f, building->fTransparency}; glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, mat1); //osvetleni if( highlightState && !building->iDummy ) drawHighlight(); //vykresli model TModelSceneObject::drawObject(); #ifdef DEBUG_DRAW_ATTACKPOSITIONS //vykresli utocne pozice drawAttackPositions(); #endif #ifdef DEBUG_DRAW_GATES //pro debug drawGates(); #endif } void TSceneBuildingObject::drawGates(){ glDisable(GL_LIGHTING); glBegin(GL_LINES); for(std::vector::iterator it = building->vApproachRoutes.begin(); it != building->vApproachRoutes.end(); it++) { TApproachRoute* ar = &(*it); for(int i = 0; i < (*it).gates_c; i++){ glVertex3f(ar->gates[i].p1.x, ar->gates[i].p1.y, 160); glVertex3f(ar->gates[i].p2.x, ar->gates[i].p2.y, 160); glVertex3f( ar->gates[i].c.x, ar->gates[i].c.y, 160); glVertex3f( ar->gates[i].c.x + ar->gates[i].norm.x*20, ar->gates[i].c.y + ar->gates[i].norm.y*20, 160); } } glEnd(); glEnable(GL_LIGHTING); } void TSceneBuildingObject::drawAttackPositions(){ glDisable(GL_LIGHTING); for(vector::iterator it = building->vAttackPositions.begin(); it != building->vAttackPositions.end(); it++) { TAttackPosition* ap = &(*it); glBegin(GL_LINE_STRIP); for(int i = 0; i < ap->points_c; i++){ glVertex3f(ap->points[i].x, ap->points[i].y, 160); } glEnd(); } glEnable(GL_LIGHTING); } /* osvit budovu */ void TSceneBuildingObject::drawHighlight(){ TVertex* verts1 = NULL; int verts1_c = getStoredVertexes("_highlight", &verts1); if(verts1_c > 0){ glDisable(GL_LIGHTING); if(highlightState == 1) glColor3f(BUILDING_SELECTION_COLOR); if(highlightState == 2) glColor3f(BUILDING_PRESELECTION_COLOR); for(int i = 0; i < verts1_c; i++){ int p1 = i?(i-1):(verts1_c-1); int p2 = i; float x1=verts1[p1].position.x; float y1=verts1[p1].position.y; float z1=verts1[p1].position.z; float x2=verts1[p2].position.x; float y2=verts1[p2].position.y; float z2=verts1[p2].position.z; //transformace Transform(mx4Pos, &x1, &y1, &z1); Transform(mx4Pos, &x2, &y2, &z2); building->map->drawLine(x1,y1,x2,y2); } glEnable(GL_LIGHTING); } } /*TFlag***********************************************************************/ void TFlag::drawObject() { //barva float mat1[] = {FLAG_COLOR, bBuilding->fTransparency}; glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, mat1); //vykresli model TModelSceneObject::drawObject(); } TFlag::TFlag(TModel* mod, TBuilding* b) :TModelSceneObject(mod) { bBuilding = b; } /*TBuilding*******************************************************************/ TBuilding::TBuilding(TguiMap* m, TGUIBuildingInfo* info) :TProxyObject(m, ptBuilding) { TControllerManager * cm = map->getCM(); bc = new TBuildingController(this); cm->addController(bc); // memcpy(&guibiInfo, info, sizeof(TGUIBuildingInfo)); // iDummy = 0; tfFlag = NULL; transparency(1); // TSceneBuildingObject *so; if(guibiInfo.underconstruction) so = new TSceneBuildingObject( this, guibiInfo.construction_mod ); else so = new TSceneBuildingObject( this, guibiInfo.mod ); // map->addObject(so); so->tag2 = TAG2_UNITLIKE; objs.push_back(so); // bc->setTimeRatio( cm->fTimeRatio, 1 ); } TBuilding::TBuilding(TguiMap* m, TGUIBuildingInfo* info, int dummy) :TProxyObject(m, ptBuilding) { bc = NULL; // memcpy(&guibiInfo, info, sizeof(TGUIBuildingInfo)); // iDummy = 1; tfFlag = NULL; transparency(0.5f); // TSceneBuildingObject *so = new TSceneBuildingObject( this, guibiInfo.mod ); // map->addObject(so); so->tag2 = TAG2_UNITLIKE; objs.push_back(so); } TBuilding::~TBuilding() { //odstran a dealokuj model budovy for(vbuildingobjs::iterator it = objs.begin(); it != objs.end(); it++) { map->remFromScene(*it); delete *it; } //odstraneni vlajky(pokud existuje) if(tfFlag){ map->remFromScene(tfFlag); delete tfFlag; } //smaz pristupove cesty for(vector::iterator arit = vApproachRoutes.begin(); arit != vApproachRoutes.end(); arit++) { KMemFree((*arit).gates); } //smaz utocne pozice for(vector::iterator apit = vAttackPositions.begin(); apit != vAttackPositions.end(); apit++) { KMemFree((*apit).points); } //dokourit for( std::vector::iterator dit = vDamage.begin(); dit != vDamage.end(); dit++) { (*dit).smoke->smokeOut(3000); } //odstran kontroler TControllerManager * cm = map->getCM(); cm->removeController(bc); } int TBuilding::addToHex(int newindex){ //umisti place(); if(!iDummy){ //pristupove cesty loadApproachRoutes(); //utocne pozice loadAttackPositions(); //poloha pro stavitele loadBuilderPosition(); } return 1; } void TBuilding::setFade(int newfade) { vbuildingobjs::iterator it; it = objs.begin(); while(it != objs.end()) { (*it)->fade = newfade; it++; } if(tfFlag){ tfFlag->fade = newfade; } } void TBuilding::dump2D(FILE* f) { for( vbuildingobjs::iterator it=objs.begin(); it!=objs.end(); it++) { P3F c = (*it)->aabbCenter; P3F d = (*it)->aabbDim; fprintf(f,"CircularObstacle\t%f\t%f\t%f\n", c.x, c.y, SizeV2(d.p)/2); } } void TBuilding::place(){ float zz[4]; P3F p3f; float z; map->hexCentre(&p3f, hexWhereIam->getIndex()); for( vbuildingobjs::iterator it=objs.begin(); it!=objs.end(); it++) { //poloha (*it)->moveTo(p3f.x, p3f.y, 0); //orientace float angle; if(guibiInfo.orientation_count) angle = -float(2*M_PI/(guibiInfo.orientation_count))*guibiInfo.orientation; else angle = -float(M_PI/3)*guibiInfo.orientation; (*it)->rotateTo( 0, 0, angle); // map->reinstalObject((*it)); (*it)->calculateAABB(); //posazeni map->altitude((*it)->aabbCenter.x-(*it)->aabbDim.x/2, (*it)->aabbCenter.y-(*it)->aabbDim.y/2,&zz[0]); map->altitude((*it)->aabbCenter.x+(*it)->aabbDim.x/2, (*it)->aabbCenter.y-(*it)->aabbDim.y/2,&zz[1]); map->altitude((*it)->aabbCenter.x+(*it)->aabbDim.x/2, (*it)->aabbCenter.y+(*it)->aabbDim.y/2,&zz[2]); map->altitude((*it)->aabbCenter.x-(*it)->aabbDim.x/2, (*it)->aabbCenter.y+(*it)->aabbDim.y/2,&zz[3]); // z = -FLT_MAX; for(int i = 0; i < 4; i ++) if( z < zz[i] )z = zz[i]; // (*it)->moveBy(0,0,z); //reinstaluj map->reinstalObject((*it)); } } TSceneBuildingObject* TBuilding::getMainStructure(){ return (TSceneBuildingObject*)(objs[0]); } void TBuilding::getPosition(P2F* pos){ P3F hc; hexWhereIam->getHexCenter(&hc); *pos = hc.p2f; } void TBuilding::script(TSceneScript* c, int startAt){ bc->script(c,startAt); } void TBuilding::remove(int startAt){ bc->remove(startAt); } void TBuilding::occupy(int player){ guibiInfo.player = player; // TSceneBuildingObject* sbo = getMainStructure(); float size = SizeV2(sbo->aabbDim.p); TSparkle::installSparkle(&(sbo->aabbCenter), size, size); } void TBuilding::setPlayer(int i){ //nastavi se barva cely budovy guibiInfo.player = i; } void TBuilding::transparency(float trans){ fTransparency = trans; } void TBuilding::changeOrientationBy(int deg, int allowed_orientations){ for( vbuildingobjs::iterator it=objs.begin(); it!=objs.end(); it++) { //orientace int sig=deg/myabs(deg);//smer int oc = 6; if(guibiInfo.orientation_count) oc = guibiInfo.orientation_count; //spocti orientaci guibiInfo.orientation=((guibiInfo.orientation+deg)%oc+oc)%oc; //otoc na najblizsi povolenou, pokud nahodou 0 tak nic while( !(allowed_orientations&(1<::iterator it = vBuilderPositions.begin(); it != vBuilderPositions.end(); it++) { dist = DISTV2( (*it).p2fPosition.p, bpos->p); if(dist < min_dist ){ min_dist = dist; nearest = &(*it); } } // if(nearest){ *pos = nearest->p2fPosition; *dir = nearest->p2fDirection; } } void TBuilding::loadBuilderPosition(){ TSceneBuildingObject* main = getMainStructure(); TVertex* verts1; int verts1_c; MX4 m; P3F center; char bpname[20]; int bpn = 1; TBuilderPosition bp; main->getPosition(¢er); main->getPositionMX4(m); // vBuilderPositions.clear(); while(1){ //zjisti si ridici body snprintf(bpname, 20, "_builderposition%d", bpn); verts1_c = main->getStoredVertexes(bpname, &verts1); if(!verts1)break; //poloha bp.p2fPosition = TVector( verts1[0].position ).transform(m).toP2F(); bp.p2fDirection = TVector( verts1[1].position ).transform(m).toP2F(); // bp.p2fDirection = ( TVector(bp.p2fDirection) - TVector(bp.p2fPosition) ).toP2F(); // vBuilderPositions.push_back(bp); bpn++; } } void TBuilding::buildingCompleted(){ //ulozit parametry & ziskat data int hex = hexWhereIam->getIndex(); int lb_indx = guibiInfo.livingbuilding; TguiMap* m = map; World::TLivingBuildingsContainer* lbc = m->getWorldLivingBuildings(); LIVING_BUILDING* lb = &( (*lbc)[lb_indx]->data() ); //odinstalovat stavbu TBuilding::uninstallBuilding(m, lb_indx); //nainstalovat budovu TBuilding* nb = TBuilding::installBuilding(m, lb_indx, lb, hex); //dokonci v postavne budove nb->buildingCompleted(); } void TBuilding::recruitUnit(int lui) { int hx, hy; map->getHexCoords(hexWhereIam->getIndex(), &hx, &hy); World::TLivingUnitsContainer* luc = map->getWorldLivingUnits(); World::LIVING_UNIT* lu = &((*luc)[lui]->data()); TUnit::installUnit(map, lui, lu, hx, hy); } /////////////////////////////////////////////////////////////////////////////// // pohyb /////////////////////////////////////////////////////////////////////////////// void TBuilding::loadApproachRoutes(){ TSceneBuildingObject* main = getMainStructure(); TApproachRoute ar; TVertex* verts1; int verts1_c; int apn; char apname[20]; MX4 m; P3F center; main->getPosition(¢er); main->getPositionMX4(m); //pristupove cesty pozice vApproachRoutes.clear(); apn = 1; while(1){ //kontrolni body snprintf(apname, 20, "_approachroute%d", apn); verts1_c = main->getStoredVertexes(apname, &verts1); if(!verts1)break; //brany ar.gates_c = (verts1_c/2); ar.gates = (TGate*)KMemAlloc( sizeof(TGate) * ar.gates_c ); for(int i = 0; i < ar.gates_c; i++){ // ar.gates[i].p1 = TVector( verts1[i*2].position ).transform(m).toP2F(); ar.gates[i].p2 = TVector( verts1[i*2+1].position ).transform(m).toP2F(); // P2F p1p2 = ( TVector( ar.gates[i].p1 ) - TVector( ar.gates[i].p2 ) ).toP2F(); P2F normal; NormalV2(p1p2.p, normal.p); // ar.gates[i].width = TVector( p1p2 ).len(); ar.gates[i].norm = TVector( normal ).norm().toP2F(); // ar.gates[i].c = ( (TVector( ar.gates[i].p1 ) + TVector( ar.gates[i].p2 )) * 0.5f ).toP2F(); } //vstup ar.enter = ar.gates[0].c; ar.enter_dir = TVector(ar.gates[0].norm).toP2F(); //vystup ar.exit_dir = TVector(ar.gates[ar.gates_c - 1].norm).toP2F(); vApproachRoutes.push_back(ar); apn++; } } int TBuilding::generateRouteOutside(P2F* out_dir, P2F* route_buff, P2F* tangent_buff, int route_buff_max, float unit_width){ TApproachRoute* ar = NULL; float dist, max_dist = -FLT_MAX; float random_element, gwr; //najdi unikovou trasu for(vector::iterator it = vApproachRoutes.begin(); it != vApproachRoutes.end(); it++) { dist = ScalMulV2( (*it).enter.p, out_dir->p ); // if( dist > max_dist){ max_dist = dist; ar = &(*it); } } //vytyc cestu if(!ar)return 0; //assert( ar ); assert( ar->gates_c < route_buff_max ); for(int j = ar->gates_c-1; j >= 0; j--){ // gwr = MIN( unit_width/((float)ar->gates[j].width), 0.5f); random_element = RAND(gwr, 1-gwr); // route_buff[ar->gates_c-1 - j ] = ( TVector(ar->gates[j].p2) + (TVector(ar->gates[j].p1) - TVector(ar->gates[j].p2)) * random_element ).toP2F(); if(tangent_buff) tangent_buff[ ar->gates_c-1 - j ] = (-TVector(ar->gates[j].norm)).toP2F(); } return ar->gates_c; } int TBuilding::generateRouteInside(P2F* in_dir, P2F* route_buff, P2F* tangent_buff, int route_buff_max, float unit_width){ TApproachRoute* ar = NULL; float dist, min_dist = FLT_MAX; float random_element, gwr; //urci pristupovou pozici for(vector::iterator it = vApproachRoutes.begin(); it != vApproachRoutes.end(); it++) { dist = ScalMulV2( (*it).enter.p, in_dir->p ); // if( dist < min_dist){ min_dist = dist; ar = &(*it); } } //vytyc cestu if(!ar)return 0; assert( ar ); assert( ar->gates_c < route_buff_max ); for(int j = 0; j < ar->gates_c; j++){ // gwr = MIN( unit_width/((float)ar->gates[j].width), 0.5f); random_element = RAND(gwr, 1-gwr); // route_buff[j] = ( TVector(ar->gates[j].p2) + (TVector(ar->gates[j].p1) - TVector(ar->gates[j].p2)) * random_element ).toP2F(); if(tangent_buff) tangent_buff[j] = ar->gates[j].norm; } return ar->gates_c; } /////////////////////////////////////////////////////////////////////////////// // boj /////////////////////////////////////////////////////////////////////////////// void TBuilding::loadAttackPositions(){ int apn; char apname[20]; TVertex* verts1; int verts1_c; TAttackPosition ap; TSceneBuildingObject* main_struct; MX4 m; // main_struct = getMainStructure(); main_struct->getPositionMX4(m); vAttackPositions.clear(); apn = 1; while(1){ //kontrolni body snprintf(apname, 20, "_attackposition%d", apn); verts1_c = main_struct->getStoredVertexes(apname, &verts1); if(!verts1)break; //body ap.points_c = (verts1_c); ap.points = (P2F*)KMemAlloc( sizeof(P2F) * ap.points_c ); SETV2(ap.attackdir.p, 0, 0); ap.len = 0; for(int i = 0; i < verts1_c; i++){ ap.points[i] = TVector( verts1[i].position ).transform(m).toP2F(); if(i>0){ //normala P2F p1p2 = ( TVector( ap.points[i-1] ) - TVector( ap.points[i] ) ).toP2F(); P2F normal; NormalV2(p1p2.p, normal.p); NormalizeV2(normal.p); AddV2(ap.attackdir.p, normal.p); //delka ap.len += DISTV2(ap.points[i].p, ap.points[i-1].p); } } NormalizeV2(ap.attackdir.p); vAttackPositions.push_back(ap); // apn++; } } void TBuilding::getAttackPosition(P2F* cpos, P2F* dir, P2F* pos){ float ang, min_ang = FLT_MAX; P2F bpos, adir; TAttackPosition *pap = NULL; // getPosition(&bpos); adir = ( TVector(bpos) - TVector(*cpos) ).toP2F(); //najdil utocnou pozici v nejlepsim smeru for(vector::iterator it = vAttackPositions.begin(); it != vAttackPositions.end(); it++) { ang = Angle2Db( &((*it).attackdir), &adir ); if( ang < min_ang ){ min_ang = ang; pap = &(*it); } } //impl hodnoty *pos = bpos; *dir = adir; //nejsou definovane utocne pozice if(!pap) return; //najdi nahodnou polohu na utocne pozici float r_factor = RAND(0, 1); float dist = 0; float seg_len = 0; P2F seg; for(int i = 1; i < pap->points_c; i++){ // seg = ( TVector(pap->points[i]) - TVector(pap->points[i - 1]) ).toP2F(); seg_len = SizeV2(seg.p); // if( (seg_len + dist)/pap->len > r_factor ){ //poloho na segmentu r_factor -= dist/pap->len; r_factor = r_factor / ( seg_len/pap->len); *pos = ( TVector(pap->points[i - 1]) + TVector(seg)*r_factor ).toP2F(); //smer *dir = pap->attackdir; // break; } dist += seg_len; } } TDistant_Attack* TBuilding::defensiveFire(TUnitMember* target){ // TSceneBuildingObject* main_struct = getMainStructure(); // TVector variation(RAND(-main_struct->aabbDim.x/2, main_struct->aabbDim.x/2), RAND(-main_struct->aabbDim.y/2, main_struct->aabbDim.y/2), 0); P3F trgpos = (TVector(main_struct->aabbCenter) + variation).toP3F(); //naplanuj strelu int t = KTime(); //rozdeleni podle typu TDistant_Attack *da = TArrowAttack::installArrowAttack(&(main_struct->aabbCenter), &trgpos, t); da->setTimeRatio(bc->fTimeRatio, 0); // return da; } /////////////////////////////////////////////////////////////////////////////// // poskozeni /////////////////////////////////////////////////////////////////////////////// void TBuilding::sufferDamage(int startAt){ // TSceneBuildingObject* mainstruct = getMainStructure(); P3F mainpos; mainstruct->getPosition(&mainpos); float rad = SizeV2(mainstruct->aabbDim.p)/2; float randa = RAND(0, 2*M_PI); float randr = RAND(0, rad); P3F pos = {mainpos.x + randr*sin(randa), mainpos.y + randr*cos(randa), mainpos.z}; // TDamage d; d.smoke = TSmoke::installSmoke(&pos, startAt, -1); d.smoke->setTimeRatio( bc->fTimeRatio, 0 ); vDamage.push_back(d); // } void TBuilding::gotHit(int startAt){ TSceneBuildingObject* mainstruct = getMainStructure(); //poloha float radius = MIN(mainstruct->aabbDim.x,mainstruct->aabbDim.y)/2; float rrad = RAND(0, radius); float rang = RAND(0,(float)(2*M_PI)); P3F scpos; mainstruct->getPosition(&scpos); scpos = (TVector(scpos)+TVector( sin(rang)*rrad, cos(rang)*rrad, 0)).toP3F(); //vyska nad povrchem P3F pos = {0, 0, ABS(mainstruct->aabbCenter.z - scpos.z)};//pramen // float ang = RAND(0, M_PI/2); P3F dir = {cos(ang),0,sin(ang)}; // TExplosion* ex; ex = TExplosion::installExplosion(&dir, &scpos, &pos, (startAt >=0 )?startAt:KTime(), 30, 15.0); //stejna rychlost jako jednotka ex->setTimeRatio( bc->fTimeRatio, 0 ); } void TBuilding::destroyBuilding(int startAt){ bc->destruction(startAt); } void TBuilding::demolishBuilding(TIntContainer h){ (new TDemolishBuilding(this, h))->ungetRef(); } void TBuilding::repairDamage(int ol, int nl, int t){ //kolik je poskozeni int s = (int)vDamage.size(); //kolik kouru int r = LIVES2DAMAGE(this, nl) - LIVES2DAMAGE(this, s); while( r && vDamage.size() ){ std::vector::iterator it = vDamage.begin(); (*it).smoke->smokeOut(3000); //vykourit vDamage.erase(it); r--; } } /////////////////////////////////////////////////////////////////////////////// // vlajka /////////////////////////////////////////////////////////////////////////////// void TBuilding::hangDownFlag(){ if(tfFlag){ map->remFromScene(tfFlag); delete tfFlag; tfFlag = NULL; } } void TBuilding::hangUpFlag(){ // TSceneBuildingObject* main = getMainStructure(); // TVertex* verts1 = NULL; int verts1_c = main->getStoredVertexes("_flagstand", &verts1); if(verts1_c>0){ P3F p; MX4 m, tr, mm; //transformace pozice vlajky do svetovych souradnic -> transf matice CopyV3(p.p, verts1[0].position.p); main->getPositionMX4(m); SetTransMX4(tr, p.x, p.y, p.z); MulMatrixMX4(mm, tr, m); // TModel* flag; //model manager rm::TRM_model_i* mrm; if( !( mrm = (rm::TRM_model_i*)KSendBcAnMsg(MSG_GET_RM_MODEL_I, 0)) ) THROW(E_8K_GUI, "TBuilding::hangUpFlag(): failed to query rmmodel interface\n"); flag = mrm->get(MODEL_FLAG); delete mrm; // tfFlag = new TFlag( flag, this ); map->addObject(tfFlag); tfFlag->setPositionMX4(mm); map->reinstalObject(tfFlag); // tfFlag->fade = main->fade; tfFlag->tag2 = TAG2_UNITLIKE; } } /////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////// void TBuilding::select(){ TSelectableObject::select(); for( vbuildingobjs::iterator m_it = objs.begin(); m_it != objs.end(); m_it++) if(!preselected)(*m_it)->highlight(2); else (*m_it)->highlight(1); } void TBuilding::unselect(){ TSelectableObject::unselect(); for( vbuildingobjs::iterator m_it = objs.begin(); m_it != objs.end(); m_it++) if(!preselected)(*m_it)->highlight(0); else (*m_it)->highlight(1); } void TBuilding::preselect(){ TSelectableObject::preselect(); for( vbuildingobjs::iterator m_it = objs.begin(); m_it != objs.end(); m_it++) (*m_it)->highlight(1); } void TBuilding::preunselect(){ TSelectableObject::preunselect(); for( vbuildingobjs::iterator m_it = objs.begin(); m_it != objs.end(); m_it++) if(selected)(*m_it)->highlight(2); else (*m_it)->highlight(0); } void TBuilding::onClick(){ map->buildingClicked_sensor(this); } /////////////////////////////////////////////////////////////////////////////// // staticke cleny /////////////////////////////////////////////////////////////////////////////// /* knihovna budov */ std::map TBuilding::buildings; /* nacti knihovnu budov */ void TBuilding::initBuildings(){ //smazat dosavadni seznam if( !TBuilding::buildings.empty() ){ for(std::map::iterator it = TBuilding::buildings.begin(); it != TBuilding::buildings.end(); it++) KMemFree( (it->second) ); TBuilding::buildings.clear(); } //model manager rm::TRM_model_i* mrm; if( !( mrm = (rm::TRM_model_i*)KSendBcAnMsg(MSG_GET_RM_MODEL_I, 0)) ) THROW(E_8K_GUI, "TBuilding::initBuildings(): failed to query rmmodel interface\n"); //vylistuj budovy rm::TRM_building_i* rmbuilding; DA* buildings_library; if( !(rmbuilding = (rm::TRM_building_i*)KSendGlobalMessage(MSG_GET_RM_BUILDING_I, MOD_GUI, MOD_RM, NULL)) ) THROW(E_8K_GUI, "TBuilding::initBuildings(): failed to query rmbuilding interface\n"); // BUILDING *b; TGUIBuildingInfo* gbi; rmbuilding->getBuildings(&buildings_library); int ord = 0; for (int k=buildings_library->getNext(-1);k!=-1;k=buildings_library->getNext(k)) { b = (*buildings_library)[k]; gbi = (TGUIBuildingInfo*)KMemAlloc(sizeof(TGUIBuildingInfo)); gbi->bid = k; gbi->positioning = 0; gbi->mod = mrm->get(b->modelid); gbi->construction_mod = mrm->get(b->construction_modelid); gbi->maxlives = b->lives; gbi->orientation = 0; gbi->orientation_count = b->orientation_count; gbi->structuretype = (TStructureType)b->structure_type; TBuilding::buildings.insert( std::make_pair(k, gbi) ); } delete mrm; delete rmbuilding; } /* vlozi spravnou budovu z knihovny */ TBuilding* TBuilding::installBuilding(TguiMap* sc, int lb_indx, LIVING_BUILDING* lb, int hindex) { //najdi zaznam v knihovne typu budov TGUIBuildingInfo* gbi = buildings[lb->type]; // if(!gbi){ THROW(E_8K_GUI, "TBuilding::installBuilding(): unknown building type\n"); } //nastaveni startovacich parametru gbi->orientation = lb->orientation; gbi->livingbuilding = lb_indx; gbi->underconstruction = (lb->construction_duration != 0); gbi->player = lb->player; //vytor budovu podle zaznamu TBuilding* building; //staveniste je otevrena budova if(gbi->structuretype == stOpenBuilding || gbi->underconstruction){ building = new TOpenStructure(sc, gbi); } else if( gbi->structuretype == stClosedBuilding && !gbi->underconstruction ) { building = new TClosedStructure(sc, gbi); } //vloz mezi budovy sc->guimap_buildings.insert( std::make_pair(lb_indx, building) ); //uloz do hexu sc->hexy[hindex]->addProxy(building); //vytvor poskozeni budovy if(!gbi->underconstruction){ int dam = LIVES2DAMAGE(building, gbi->maxlives) - LIVES2DAMAGE(building, lb->lives); for(int i = 0; i < dam; i++) building->sufferDamage(0); } return building; } TBuilding* TBuilding::installDummyBuilding(TguiMap* sc, int bid, int hindex, int allowed_orientations){ //najdi zaznam v knihovne typu budov TGUIBuildingInfo* gbi = buildings[bid]; // if(!gbi){ THROW(E_8K_GUI, "TBuilding::installDummyBuilding(): unknown building type\n"); } //nastaveni startovacich parametru gbi->orientation = 0; while( !(allowed_orientations&(1<orientation)) && allowed_orientations )gbi->orientation++; gbi->livingbuilding = -1; gbi->underconstruction = 0; gbi->player = 0; //vytor budovu podle zaznamu TBuilding* building; // building = new TBuilding(sc, gbi, 1); //uloz do hexu sc->hexy[hindex]->addProxy(building); return building; } void TBuilding::uninstallDummyBuilding(TguiMap* sc, TBuilding* b){ b->hexWhereIam->remProxy(b); delete b; } void TBuilding::uninstallBuilding(TguiMap* sc, int lb_indx){ gui::TBuilding* gui_building_instance = NULL; //odstraneni z vesaku budov gui_building_instance = sc->guimap_buildings[lb_indx]; sc->guimap_buildings.erase(lb_indx); // if(!gui_building_instance) THROW(E_8K_GUI, "TBuilding::uninstallBuilding(): gui instance of building does not exist\n"); //odstraneni z hexu if(gui_building_instance->hexWhereIam) gui_building_instance->hexWhereIam->remProxy(gui_building_instance); //vzrus delete gui_building_instance; } void TBuilding::freeBuildings(){ // if( !TBuilding::buildings.empty() ){ for(std::map::iterator it = TBuilding::buildings.begin(); it != TBuilding::buildings.end(); it++) KMemFree( (it->second) ); TBuilding::buildings.clear(); } } /*uzavrene budovy**************************************************************/ TClosedStructure::TClosedStructure(TguiMap* m, TGUIBuildingInfo* info) :TBuilding(m, info) { } void TClosedStructure::buildingCompleted(){ if(guibiInfo.underconstruction) { //zmen model TBuilding::buildingCompleted(); } else { TUnit* unit = (TUnit*)hexWhereIam->getProxy(ptDynamic); //schovej dovnitr if(unit) { unit->transparency(0); hangUpFlag(); }//if }//else } /*otevrene budovy**************************************************************/ TOpenStructure::TOpenStructure(TguiMap* m, TGUIBuildingInfo* info) :TBuilding(m, info) { } int TOpenStructure::addToHex(int newindex){ TBuilding::addToHex(newindex); //natahni data o shromazdistich findPlacementAreas(); return 1; } void TOpenStructure::buildingCompleted(){ //stavitele do budovy if(guibiInfo.underconstruction) { //zmen model TBuilding::buildingCompleted(); } else { // clearPositions(); } } void TOpenStructure::findPlacementAreas(){ TSceneBuildingObject* structure = getMainStructure(); TVertex* verts = NULL; TPlacementArea parea; int verts_c = structure->getStoredVertexes("_placementarea", &verts); MX4 m; // structure->getPositionMX4(m); // placement.clear(); for(int i = 0; i < verts_c/4 ; i++) { parea.vp3fCorner[0] = TVector(verts[i*4].position).transform(m).toP2F(); parea.vp3fCorner[1] = TVector(verts[i*4+1].position).transform(m).toP2F(); parea.vp3fCorner[2] = TVector(verts[i*4+2].position).transform(m).toP2F(); parea.vp3fCorner[3] = TVector(verts[i*4+3].position).transform(m).toP2F(); parea.vp3fAreaBase[0] = ( TVector(parea.vp3fCorner[1]) - TVector(parea.vp3fCorner[0]) ).toP2F(); parea.vp3fAreaBase[1] = ( TVector(parea.vp3fCorner[3]) - TVector(parea.vp3fCorner[0]) ).toP2F(); // parea.fWidth = TVector(parea.vp3fAreaBase[0]).len(); parea.fHeight = TVector(parea.vp3fAreaBase[1]).len(); // parea.vp3fAreaBase[0] = TVector(parea.vp3fAreaBase[0]).norm().toP2F(); parea.vp3fAreaBase[1] = TVector(parea.vp3fAreaBase[1]).norm().toP2F(); // placement.push_back(parea); } } void TOpenStructure::clearPositions(){ positions.clear(); } int TOpenStructure::findPosition(P2F* dim, P2F* pos) { vector::iterator it; int maxIterations = 100; int col = 0; //poloha TUnitMemberPosition ump; ump.p2fDim = *dim; SETV2(ump.p2fPos.p, 0, 0); SETV2(ump.p2fDir.p, 1, 0); // it = placement.begin(); assert( it!=placement.end() ); float bx[2] = {dim->x/2, ((*it).fWidth-dim->x/2)}; float by[2] = {dim->y/2, ((*it).fHeight-dim->y/2)}; while(1){ //nahodne vygeneruj float x = RAND( bx[0], bx[1] ); float y = RAND( by[0], by[1] ); //spocitej pomoci baze a pocatku ump.p2fPos = ( TVector( (*it).vp3fCorner[0] ) + TVector((*it).vp3fAreaBase[0])*x + TVector((*it).vp3fAreaBase[1])*y ).toP2F(); //kolize col = 0; for( vector::iterator pit = positions.begin(); pit != positions.end(); pit++) { //kolize float ir = intersectionRatio(&ump, &(*pit)); // if( ir > 0 ){ col = 1; break; } } // maxIterations--; if(maxIterations<0)break; // it++; if(it == placement.end()) it = placement.begin(); if(col)continue; else break; } positions.push_back(ump); *pos = ump.p2fPos; // return col; } /* zkoliduje s povrchem */ void TOpenStructure::surfaceAltitude(float x, float y, float *z){ // TSceneBuildingObject* structure = getMainStructure(); // TMeshNode *mn = structure->getCheckPoint("_surface"); if(!mn) return; //transformuj do object spacu TRay r(x, y, 1000, 0, 0, -1, 0, 1000); Transform( structure->inverse, r.start.p); // P3F col; TPolygon* p; // if( CollideMesh( mn->obj->mesh + mn->mesh, &r, &col, &p) ) { //transformuj do world spacu MX4 mx4; structure->getPositionMX4(mx4); // Transform( mx4, col.p); *z = col.z; } } }//namespace /*****************************************************************************/