/** ******************************************************************************* @file /gui/model/guiUnit.cpp @brief Reprezentace jednotky(vojacku) -vicemene obaluji modely a skupiny modelu -volaji jejich kontrolery -spousteji skripty Makro DEBUG_DRAW_PATH aktivuje vykreslovani cesty. @author Vajicek @version 0.1 ******************************************************************************/ #include #include "gui/model/guiUnit.h" #include "gui/model/ModelRep.h" #include "gui/model/guimap.h" #include "gui/common/colors.h" #include "gui/common/mymath_ext.h" #include "common/Log.h" #include "common/rm/rminit.h" #include "gui/common/Sounds.h" #ifdef _DEBUG static TLog unit_logger(1); #endif #define LOG //unit_logger.LogMsg // vypnout varovani pri prekladu #pragma warning( disable : 4355 ) namespace gui{ using namespace World; //----------------------------------------------------------------------------- /// doba do zmizeni mrtveho tela #define DEATH_BODY_DISAPPEAR_TIME 10000 /// doba po jakou telo mizi #define DEATH_BODY_DISAPPEAR_DUR 15000 /// maximalni doba do zacatku akce #define MAX_ACTION_DELAY 500 /// vykreslovavat trasy pro steering #ifdef STEERING #define DEBUG_DRAW_STEERING_ROUTES #endif TUnitMember::TUnitMember(TModel *mid, TControllerManager* ccm, TUnit* u) :TModelSceneObject(mid) #ifdef SIMPLE_SHADOWS , TSimpleShadow(this, RASTER_SHADOW) #endif { fTransparency = 1; iLastAnimationEnd = 0; umsState = umsLive; unit = u; //rychlost panacka fDiferentiate = RAND(0.9f,1.1f); //velikost podsvetleni calculateAABB(); fHighlightSize = SizeV2(aabbDim.p2f.p) / 2; //priorita vyberu iPriorityOfSelection = 5; //kontroler pro animace pc = new TPuppetController(inst); pc->setTimeRatio(fDiferentiate, 1); unit->uc->addChildControler(pc); //kontroler pro pohyb umc = new TUnitMemberController(this); umc->setTimeRatio(fDiferentiate, 1); unit->uc->addChildControler(umc); #ifdef STEERING //kontroler pro steering sc = new TSteeringController(u->map->skc, this); sc->setTimeRatio(fDiferentiate, 1); unit->uc->addChildControler(sc); #else sc = NULL; #endif } TUnitMember::~TUnitMember(){ //odstran ze sceny unit->map->remFromScene(this); //odstran unit member controller unit->uc->removeChildControler(umc); //odstran puppet controller unit->uc->removeChildControler(pc); //odstran steering controller if(sc)unit->uc->removeChildControler(sc); //odstran z jednotky unit->removeMember(this); } void TUnitMember::drawObject() { //neviditelni se vubec nevykreslujou if(fTransparency > 0){ // #ifdef DEBUG_DRAW_PATH drawPath(); #endif // #ifdef DEBUG_DRAW_STEERING_ROUTES if(sc)sc->draw(unit->map); #endif // #ifdef SIMPLE_SHADOWS if (getRealFade() < 3) drawShadow(); #endif drawHighlight(); // float mat[] = {ColorPlayer[ unit->guiuiInfo.player ][0]/255.0f, ColorPlayer[ unit->guiuiInfo.player ][1]/255.0f, ColorPlayer[ unit->guiuiInfo.player ][2]/255.0f, fTransparency}; glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, mat); // TModelSceneObject::drawObject(); } } /////////////////////////////////////////////////////////////////////////////// // akce /////////////////////////////////////////////////////////////////////////////// void TUnitMember::walk(){ playAnimation(MODEL_ANIM_WALK, PC_LOOP, KTime()); } void TUnitMember::fight(TUnitMember* target){ //sermuj s protivnikem int t = KTime() + (int)(RAND(0, MAX_ACTION_DELAY)/umc->fTimeRatio); playAnimation(MODEL_ANIM_FIGHT, PC_LOOP, t); //cas reakce int fight_reaction_ts = 1500; //reakce cile float rnd = RAND(0,1); // if( rnd < 0.05f) target->bleed(t+fight_reaction_ts); else target->gothit(t+fight_reaction_ts); } void TUnitMember::fight(TBuilding* target){ //utok na budovu int t = KTime() + (int)(RAND(0, MAX_ACTION_DELAY)/umc->fTimeRatio); playAnimation(MODEL_ANIM_FIGHT, PC_LOOP, t); } TDistant_Attack* TUnitMember::fire(TUnitMember* target){ //naplanuj strelu int t = KTime() + (int)(RAND(0, MAX_ACTION_DELAY)/umc->fTimeRatio); playAnimation(MODEL_ANIM_DISTANTATTACK, 0, t); //TODO synchronizacni body v animaci(ted ma vyletet sip) int projectile_leave_ts = ROUND(2566/pc->fTimeRatio); // TVector variation(RAND(-target->aabbDim.x/2, target->aabbDim.x/2), RAND(-target->aabbDim.y/2, target->aabbDim.y/2), 0); P3F trgpos = (TVector(target->aabbCenter) + variation).toP3F(); //rozdeleni podle typu TDistant_Attack *da = NULL; switch(unit->guiuiInfo.attackType){ case atArcherAttack: da = TArrowAttack::installArrowAttack(&aabbCenter, &trgpos, t+projectile_leave_ts); break; case atCatapultAttack: da = TCatapultAttack::installCatapultProjectile(&aabbCenter, &trgpos, t+projectile_leave_ts); break; case atMagicMissileAttack: da = TMagicMissileAttack::installMagicMissileAttack(&aabbCenter, &trgpos, t+projectile_leave_ts); break; } // return da; } TDistant_Attack* TUnitMember::fire(TBuilding* target){ //naplanuj strelu int t = KTime() + (int)(RAND(0, MAX_ACTION_DELAY)/umc->fTimeRatio); TSceneBuildingObject* main_struct = target->getMainStructure(); playAnimation(MODEL_ANIM_DISTANTATTACK, 0, t); //TODO synchronizacni body v animaci(ted ma vyletet sip) int projectile_leave_ts = ROUND(2566/pc->fTimeRatio); // 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(); //rozdeleni podle typu TDistant_Attack *da = NULL; switch(unit->guiuiInfo.attackType){ case atArcherAttack: da = TArrowAttack::installArrowAttack(&aabbCenter, &trgpos, t+projectile_leave_ts); break; case atCatapultAttack: da = TCatapultAttack::installCatapultProjectile(&aabbCenter, &trgpos, t+projectile_leave_ts); break; case atMagicMissileAttack: da = TMagicMissileAttack::installMagicMissileAttack(&aabbCenter, &trgpos, t+projectile_leave_ts); break; } // return da; } void TUnitMember::bleed(int startAt){ P3F pos = {0, 0, aabbDim.z/2};//pramen P3F scpos; P3F dir; // getPosition(&scpos); getDirection(&dir); dir.z = 1; // TBloodSplash* bs; bs = TBloodSplash::installSmallBloodSplash(&dir, &scpos, &pos, (startAt >=0 )?startAt:KTime() ); //stejna rychlost jako jednotka bs->setTimeRatio( umc->fTimeRatio, 0 ); } void TUnitMember::die(int startAt){ //kdy umrit if(startAt == -1) startAt = KTime(); //odstran z zivych umsState = umsDead; //prehod mezi mrtve unit->vMembers.remove(this); unit->vDeadMembers.push_back(this); //zrus podsvetleni highlight(0); if(sc)sc->deactivate(0); umc->removeAllActions(); //nastav animace stopAllAnimations(PC_IMMEDIATE_STOP); playAnimation(MODEL_ANIM_DIE, 0, startAt); bleed(); umc->fadeout(DEATH_BODY_DISAPPEAR_DUR, startAt + DEATH_BODY_DISAPPEAR_TIME); umc->disappear(); // //prehrej zvuk if(TSoundInterface::si) TSoundInterface::si->playSampleSpatialConrolled( unit->guiuiInfo.soundsid[SOUND_COMMAND_DEATH], &aabbCenter); } void TUnitMember::flyAway(int startAt){ //kdy umrit if(startAt == -1) startAt = KTime(); //odstran z zivych umsState = umsDead; //prehod mezi mrtve unit->vMembers.remove(this); unit->vDeadMembers.push_back(this); //zrus podsvetleni highlight(0); if(sc)sc->deactivate(0); umc->removeAllActions(); //nastav animace stopAllAnimations(PC_IMMEDIATE_STOP); playAnimation(MODEL_ANIM_DIE, 0, startAt); umc->fadeout(DEATH_BODY_DISAPPEAR_DUR, startAt + DEATH_BODY_DISAPPEAR_TIME); TFlyAway::installFlyAway( this, 0.2f, 50, 5000, startAt ); } void TUnitMember::gothit(int startAt){ } void TUnitMember::fadeout(){ umc->fadeout(); } void TUnitMember::fadein(){ umc->fadein(); } /////////////////////////////////////////////////////////////////////////////// // animace /////////////////////////////////////////////////////////////////////////////// int TUnitMember::playAnimation(int id, int flags, int startAt){ int alen = ROUND(pc->playAnimation(id, flags, startAt)/pc->fTimeRatio); if((alen+startAt)>iLastAnimationEnd) iLastAnimationEnd = (alen+startAt); return alen; } void TUnitMember::stopAnimation(int id, int flag){ pc->stopAnimation(id, flag); } void TUnitMember::stopAllAnimations(int flag){ pc->stopAllAnimations(flag); } /////////////////////////////////////////////////////////////////////////////// // pohyb /////////////////////////////////////////////////////////////////////////////// void TUnitMember::go(int pos_c, P2F* pos, P2F* tangents, int startAt){ umc->planWalk(pos_c, pos, tangents, startAt); } void TUnitMember::go(P2F* pos, P2F* dir, int startAt){ umc->planWalk(1, pos, dir, startAt); } void TUnitMember::script(TSceneScript* c, int startAt){ umc->script(c, startAt); } void TUnitMember::getDirection(P3F* dir){ MX4 mx4; P3F p1; getPositionMX4(mx4); getPosition(&p1); // P4F d1,d2; SETV4(d1.p, 0, 1, 0, 1); ApplyVectorMX4(d1.p, mx4, d2.p); CopyV4toV3(dir->p, d2.p); SubV3(dir->p, p1.p); } void TUnitMember::getModelDim(P2F* dim){ *dim = inst->model_class->aabb.aabbDim.p2f; } void TUnitMember::place(P3F* pos, P3F* dir, P3F* up) { if(pos){ unit->map->altitude(pos->x, pos->y, &(pos->z)); TModelSceneObject::setPosition(pos); } if(dir && up)TModelSceneObject::setOrientation(dir, up); unit->map->reinstalObject(this); } void TUnitMember::setTransparency(float t) { selectable = !(t == 0); fTransparency = t; } /////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////// void TUnitMember::onMouseOver(){ if((fTransparency>0.05f) && (umsState == umsLive)) unit->onMouseOver(); } void TUnitMember::onClick(){ //na neviditelny a mrtvoly se neklika if((fTransparency>0.05f) && (umsState == umsLive)) unit->onClick(); //dbg unit->subselectedmember=this; } /////////////////////////////////////////////////////////////////////////////// // zvyrazneni /////////////////////////////////////////////////////////////////////////////// void TUnitMember::drawHighlight(){ if(highlightState){ // if(highlightState == 1) glColor3f(UNIT_SELECTION_COLOR); if(highlightState == 2) glColor3f(UNIT_PRESELECTION_COLOR); unit->map->drawCircle(aabbCenter.x, aabbCenter.y, fHighlightSize); } } void TUnitMember::drawPath(){ TGenericCurve* gc; P3F p; float z = 0; // if( umc->curpath ){ gc = umc->curpath; // glBegin(GL_LINE_STRIP); for(int i = 0; i < 51; i++){ gc->eval(i/50.0f, &p); if(unit) unit->map->altitude(p.x,p.y,&z); glVertex3f(p.x, p.y, z+5); } glEnd(); } } void TUnitMember::dumpActions(){ umc->dumpActions(); } //----------------------------------------------------------------------------- /* Zkonstruuje panacky jednotky a umisti je do sceny */ TUnit::TUnit(TguiMap* scene, TGUIUnitInfo* info) :TProxyObject(scene, ptDynamic) { TControllerManager* cm; //uloz si info memcpy(&guiuiInfo, info, sizeof(TGUIUnitInfo)); //kontroler cm = map->getCM(); uc = new TUnitController(this); cm->addController(uc); //vytvor formaci switch(info->formation){ case ftHorseFormation: formation = new THorseFormation(this); break; case ftFootMenFormation: formation = new TFootMenFormation(this); break; case ftIndividualFormation: formation = new TIndividualFormation(this); break; } iUninstalled = 0; //vytvor instance modelu for(int i = 0; i < guiuiInfo.iMenCount; i++){ addMember(0); } //umisti jednotku na mape THex* hex; P3F hc; P2F d; int hi; //pozice hexu hex = map->getHex(guiuiInfo.hexx, guiuiInfo.hexy); hi = map->getHexIndex(guiuiInfo.hexx, guiuiInfo.hexy); //nastaveni prekazky formation->avoidTerrainObstacles( (TTerrainEntity*)hex->getProxy(ptTerrain) ); //nastav polohu a orientaci formace map->hexCentre(&hc, hi); calculateOrientation(guiuiInfo.orientation, &d); formation->setStandardFormation(&(hc.p2f), &d); //umisteni jednotek do budov gui::TBuilding* b = (gui::TBuilding*)hex->getProxy(ptBuilding); if(b) { setInside(b); b->hangUpFlag(); } //umisteni do terenu else { //umisti ve scene podle formace formation->setToFormation(); } //nastav rychlost uc->setTimeRatio( cm->fTimeRatio, 1 ); } TUnit::~TUnit() { //zrus formaci delete formation; //smaz panacky vunitmember::iterator m_it; m_it = vMembers.begin(); while( m_it != vMembers.end() ){ (*m_it)->ungetRef(); m_it = vMembers.begin(); } m_it = vDeadMembers.begin(); while( m_it != vDeadMembers.end() ){ //delete (*m_it)->ungetRef(); m_it = vDeadMembers.begin(); } //odstran unit controller TControllerManager * cm = map->getCM(); cm->removeController(uc); } /////////////////////////////////////////////////////////////////////////////// // info /////////////////////////////////////////////////////////////////////////////// int TUnit::getUnitMemberCount(){ return (int)vMembers.size(); } TFormation* TUnit::getFormation(){ return formation; } void TUnit::getUnitPos(P2F* p, P2F* d){ formation->getUnitPos(p, d); } void TUnit::dump2D(FILE* f) { for( vunitmember::iterator m_it = vMembers.begin(); m_it != vMembers.end(); m_it++) { P3F c = (*m_it)->aabbCenter; P3F d = (*m_it)->aabbDim; fprintf(f,"CircularObstacle\t%f\t%f\t%f\n", c.x, c.y, SizeV2(d.p)/2); } } /////////////////////////////////////////////////////////////////////////////// // akce jednotky /////////////////////////////////////////////////////////////////////////////// void TUnit::gotoHex(TPath *path){ //vytvor scenar pro pohyb (new TMarchMove(this, path))->ungetRef(); } void TUnit::attack(TUnit* u, TBuilding* b, int kills, int loss, int damage, int akilled, int dkilled, int bdestroyed, TIntContainer* ah, TIntContainer* dh) { P2F dp, dd; P2F ap, ad; P2F bp; P2F dir, ddir; //rozcestnik utoku TCombat* c = NULL; //smer a pozice utocnika a cile getUnitPos(&ap, &ad); if(u){ u->getUnitPos(&dp, &dd); dir = ( TVector(dp)-TVector(ap) ).toP2F(); } else if(b){ b->getPosition(&bp); dir = ( TVector(bp)-TVector(ap) ).toP2F(); } //nastav pozici pro ustup utocnika(utocna pozice strelce) if( !hexWhereIam->getProxy(ptBuilding) ) formation->setStandardFormation(&ap, &dir); //(1) BOJ NA BLIZKO if( guiuiInfo.attackType == atFaceToFace ){ //(1a) UTOK NA BUDOVU if(b && !u){ c = new TBuildingAttack(this, NULL, b, kills, loss, akilled!=0, dkilled!=0, damage, bdestroyed!=0, ah, dh); } //UTOK NA BUDOVU S JEDNOTKOU else if(u && b){ //(1b) UTOK NA OTEVRENOU BUDOVU if( OPENBUILDING(b) ) { c = new TOpenBuildingCombat(this, u, b, kills, loss, akilled!=0, dkilled!=0, damage, bdestroyed!=0, ah, dh); } //(1c) UTOK NA UZAVRENOU BUDOVU else{ c = new TBuildingAttack(this, u, b, kills, loss, akilled!=0, dkilled!=0, damage, bdestroyed!=0, ah, dh); } } //UTOK NA JEDNOTKU else if(u){ //nastav pozici obrance ddir = ( -TVector(dir) ).toP2F(); u->formation->setStandardFormation(&dp, &ddir); //(1d) UTOK Z BUDOVY if( hexWhereIam->getProxy(ptBuilding) ) { //specialni scenar pro boj z budov c = new TOpenBuildingCombat(this, u, NULL, kills, loss, akilled!=0, dkilled!=0, 0, false, ah, dh); } //(1e) UTOK Z POLE else{ //nastav pozici pro ustup utocnika formation->setStandardFormation(&ap, &dir); //vytvor boj, zahaj boj podle vysledku c = new TCloseCombat(this, u, kills, loss, akilled!=0, dkilled!=0, ah, dh); } } } //(2) VYBUCH if( guiuiInfo.attackType == atBlastAttack ){ c = new TBlastAttack(this, u, b, kills, loss, akilled!=0, dkilled!=0, damage, bdestroyed!=0, ah, dh); } //(3) STRELBA else if( DISTANT( guiuiInfo.attackType ) ){ c = new TDistantCombat(this, u, b, kills, loss, akilled!=0, dkilled!=0, damage, bdestroyed!=0, ah, dh); } if(c)c->ungetRef(); } void TUnit::realeaseUnit(TIntContainer h){ (new TReleaseUnit(this, h))->ungetRef(); } void TUnit::build(int site_hex_indx, int living_building_id, LIVING_BUILDING* lb){ //vytvori se budova nejakyho typu TBuilding* b = TBuilding::installBuilding(map, living_building_id, lb, site_hex_indx); //nastavit stavitele guiuiInfo.building = 1; //spust scenar (new TBuildBuilding(this, b, map->hexy[site_hex_indx]))->ungetRef(); } void TUnit::repair(int bhex, TBuilding* b, TIntContainer s, TIntContainer h){ //nastav jako stavitele guiuiInfo.building = 1; //scenar pro opravu (new TRepairBuilding(this, b, s, h))->ungetRef(); } void TUnit::heal(){ P3F hc; hexWhereIam->getHexCenter(&hc); TSparkle::installHearts(&hc, 150, 150); } void TUnit::recruit(int i){ P3F hc; //individuality nejde pridavat if( guiuiInfo.formation != ftIndividualFormation ) { for(int j = 0; j < i; j++) addMember(1); } // hexWhereIam->getHexCenter(&hc); TSparkle::installHeads(&hc, 150, 150); } void TUnit::stopBuilding(){ //nastav jako stavitele TBuilding* b = (TBuilding*)hexWhereIam->getProxy(ptBuilding); guiuiInfo.building = 0; //TODO: nejaka animace } void TUnit::desert(){ TIntContainer h; (new TUnitDeserted(this, h))->ungetRef(); } void TUnit::membersDied(int count){ (new TUnitMemberDied(this, count))->ungetRef(); } /////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////// void TUnit::setInside(gui::TBuilding* b){ P2F dim; P3F pos; P3F dir={1,0,0}; P3F up={0,0,1}; //uzavrena budova if( CLOSEDBUILDING(b) ) { // b->hexWhereIam->getHexCenter(&pos); for( vunitmember::iterator m_it = vMembers.begin(); m_it != vMembers.end(); m_it++) { (*m_it)->place(&pos, &dir, &up); } // transparency(0); } //otevrene budovy else { TOpenStructure* os = (TOpenStructure*)b; os->clearPositions(); // for( vunitmember::iterator m_it = vMembers.begin(); m_it != vMembers.end(); m_it++) { if( guiuiInfo.building ){ P2F p, bc; //z orientace jednotky zjistit polohu vzhledem k budove calculateOrientation(guiuiInfo.orientation, &p); b->getPosition(&bc); MulV2(p.p, 150); AddV2(bc.p, p.p); //najit spravne misto pro stavitele b->findNearestBuilderPosition(&p, &(pos.p2f), &(dir.p2f)); } else{ (*m_it)->getModelDim(&dim); os->findPosition(&dim, &(pos.p2f)); } (*m_it)->place(&pos, &dir, &up); } // transparency(1); } } void TUnit::transparency(float f){ for( vunitmember::iterator m_it = vMembers.begin(); m_it != vMembers.end(); m_it++) (*m_it)->setTransparency(f); } void TUnit::removeMember(TUnitMember* um){ vunitmember::iterator m_it; int erased = 0; //odstran z zivych for( m_it = vMembers.begin(); m_it != vMembers.end(); m_it++) { if( (*m_it) == um ){ vMembers.erase(m_it); erased = 1; break; } } //odstran z mrtvych if(!erased) for( m_it = vDeadMembers.begin(); m_it != vDeadMembers.end(); m_it++) { if( (*m_it) == um ){ vDeadMembers.erase(m_it); erased = 1; break; } } //podminene zruseni jednotky if( vMembers.empty() && vDeadMembers.empty() && iUninstalled) { delete this; } } TUnitMember* TUnit::addMember(int i){ TUnitMember* unitmember = new TUnitMember(guiuiInfo.unit_model, NULL, this); vMembers.push_back( unitmember ); map->addObject( unitmember ); unitmember->tag2 = TAG2_UNITLIKE; //urychli na rychlost jednotky uc->setTimeRatio(uc->fTimeRatio, 1); //umisti if(i) { TBuilding* b = (TBuilding*)hexWhereIam->getProxy(ptBuilding); //do budovy if( b ) { P2F dim; P3F pos; P3F dir={1,0,0}; P3F up={0,0,1}; //uzavrena budova if( CLOSEDBUILDING(b) ) { b->hexWhereIam->getHexCenter(&pos); unitmember->place(&pos, &dir, &up); unitmember->setTransparency(0); } //otevrene budovy else { TOpenStructure* os = (TOpenStructure*)b; // unitmember->getModelDim(&dim); os->findPosition(&dim, &(pos.p2f)); unitmember->place(&pos, &dir, &up); unitmember->setTransparency(1); } } // na pole else { P3F p = {0, 0, 0}; P3F d = {0, 0, 0}; P3F u = {0, 0, 1}; int no = (int)(vMembers.size() - 1); //najsi misto ve formaci. formation->findFreeMemberPosition(no, &(p.p2f), &(d.p2f)); //nastav pozici unitmember->calculateAABB(); unitmember->place(&p, &d, &u); } } // return unitmember; } void TUnit::calculateOrientation(int dir, P2F* d){ float angle; angle = -float(M_PI/3)*dir; SETV2(d->p,(float)sin(angle),-(float)cos(angle)); } int TUnit::addToHex(int newindex){ return 1; } void TUnit::setFade(int newfade) { vunitmember::iterator it; it = vMembers.begin(); while(it != vMembers.end()) { (*it)->fade = newfade; it++; } } void TUnit::setTimeRatio(float r){ uc->setTimeRatio(r, 1); } /////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////// void TUnit::preselect(){ TSelectableObject::preselect(); for( vunitmember::iterator m_it = vMembers.begin(); m_it != vMembers.end(); m_it++) (*m_it)->highlight(1); } void TUnit::preunselect(){ TSelectableObject::preunselect(); for( vunitmember::iterator m_it = vMembers.begin(); m_it != vMembers.end(); m_it++) if(selected)(*m_it)->highlight(2); else (*m_it)->highlight(0); } void TUnit::select(){ TSelectableObject::select(); for( vunitmember::iterator m_it = vMembers.begin(); m_it != vMembers.end(); m_it++) if(!preselected)(*m_it)->highlight(2); else (*m_it)->highlight(1); } void TUnit::unselect(){ TSelectableObject::unselect(); for( vunitmember::iterator m_it = vMembers.begin(); m_it != vMembers.end(); m_it++) if(!preselected)(*m_it)->highlight(0); else (*m_it)->highlight(1); } void TUnit::onClick(){ map->unitClicked_sensor(this); } /////////////////////////////////////////////////////////////////////////////// // inicializace z RM /////////////////////////////////////////////////////////////////////////////// std::map TUnit::units; void TUnit::initUnits(){ //smazat dosavadni seznam if( TUnit::units.size() ){ for(std::map::iterator it = TUnit::units.begin(); it != TUnit::units.end(); it++) KMemFree( (it->second) ); TUnit::units.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"); //vylistovani z RM rm::TRM_advxml_i* rmunit; DA* units_library; if( !(rmunit = (rm::TRM_advxml_i*)KSendGlobalMessage(MSG_GET_RM_UNIT_I, MOD_GUI, MOD_RM, NULL)) ) THROW(E_8K_GUI, "TUnit::initUnits(): failed to query rmunit interface\n"); //ziskej info o vsech jednotkach World::UNIT *u; TGUIUnitInfo* gui; rmunit->getAll(&units_library); for (int k=units_library->getNext(-1);k!=-1;k=units_library->getNext(k)) { u = (*units_library)[k]; // gui = (TGUIUnitInfo*)KMemAlloc(sizeof(TGUIUnitInfo)); gui->uid = k; gui->unit_model = mrm->get(u->modelid); gui->srgunit_model = NULL; // switch(u->type){ case UT_INFANTRY: gui->formation = ftFootMenFormation; break; case UT_CAVALRY: gui->formation = ftHorseFormation; break; case UT_VEHICLE: case UT_INDIVIDUAL: case UT_BEAST: case UT_FLYING: gui->formation = ftIndividualFormation; break; } // typ utoku if(u->attack_range == 0) gui->attackType = atNonCombat; else switch(u->fight_type){ case FT_FACE_TO_FACE: gui->attackType = atFaceToFace; break; case FT_BLAST: gui->attackType = atBlastAttack; break; case FT_FIRE: gui->attackType = atArcherAttack; break; case FT_CATAPULT: gui->attackType = atCatapultAttack; break; case FT_MAGIC: gui->attackType = atMagicMissileAttack; break; } // gui->iMenCount = u->max_lives; gui->iMenInRow = u->men_in_row; for(int i = 0; i < 10; i++)gui->soundsid[i] = u->soundsid[i]; // switch(u->type){ case UT_INFANTRY: gui->speed = 0.01f; break; case UT_CAVALRY: gui->speed = 0.02f; case UT_VEHICLE: case UT_INDIVIDUAL: case UT_BEAST: case UT_FLYING: gui->speed = 0.014f; break; } // TUnit::units.insert( std::make_pair(k, gui) ); } delete mrm; delete rmunit; } //todo: presunout do konstruktoru TUnit* TUnit::installUnit(TguiMap* scene, int lu_indx, LIVING_UNIT* lu, int x, int y) { // TGUIUnitInfo* gui = units[lu->type]; // if(!gui){ THROW(E_8K_GUI, "TUnit::installUnit(): unknown unit type\n"); } // gui->orientation = lu->orientation; gui->livingunit = lu_indx; gui->hexx = x; gui->hexy = y; gui->player = lu->player; gui->building = (lu->state == US_HAS_STARTED_BUILDING) || (lu->state == US_BUILDING); gui->iMenCount = (gui->formation == ftIndividualFormation)?1:lu->lives; TUnit* unit = new TUnit(scene, gui); //uloz mezi jednotky scene->guimap_units.insert( std::make_pair(lu_indx, unit) ); //uloz do hexu scene->hexy[scene->getHexIndex(x, y)]->addProxy(unit); return unit; } void TUnit::uninstallUnit(TguiMap* scene, int lu_indx, int dispose_unit){ gui::TUnit* gui_unit_instance = NULL; //odstraneni z jednotkek gui_unit_instance = scene->guimap_units[lu_indx]; scene->guimap_units.erase(lu_indx); // if(!gui_unit_instance) THROW(E_8K_GUI, "TUnit::uninstallUnit(): gui instance of unit does not exist\n"); //odstraneni z hexu if(gui_unit_instance->hexWhereIam) gui_unit_instance->hexWhereIam->remProxy(gui_unit_instance); //odinstalovano gui_unit_instance->iUninstalled = 1; //zrus pokud musis, nebo pokud uz nejsou clenove, kteri by to udelali if( dispose_unit || (gui_unit_instance->vMembers.empty() && gui_unit_instance->vDeadMembers.empty()) ) delete gui_unit_instance; } void TUnit::freeUnits(){ //smazani knihovny if( !TUnit::units.empty() ){ for(std::map::iterator it = TUnit::units.begin(); it != TUnit::units.end(); it++) { KMemFree( (it->second) ); } TUnit::units.clear(); } } }//namespace /*****************************************************************************/