All streams
Search
Write a publication
Pull to refresh
140
0
Павел Галаничев @old_gamer

Пользователь

Send message
Мне вот салон 3ки безумно понравился на картинках. В живую их не найти. Очередь тут на конец 2019го.
Х наворочен и поэтому немного обидно, что С, которая попроще, стоит столько же, если батарейка одинаковая с Х. То есть, создается впечатление, что, покупая С, ты платишь столько же, а получаешь меньше, чем Х.
Но в итоге нам С тоже понравилась больше.
И да, на 75 кВт батарейке Х все же прилично меньше, чем С проедет, а 100 кВт сильно дороже.
Не везде такая буксировка законна. Да и не с каждой фурой попути. В общем, расчитывать на такой способ все же не стоит.
Я, наверное, непонятно написал. Речь о парковке, когда надо руль постоянно крутить от упора до упора, на маленькой скорости или на месте. Такое ощущение, что жгут наматываешь, не особо приятно.
Совершенно с Вами согласен, и те же мысли не дают покоя. Но машина нужна сейчас.
Вначале думали взять подержаный Ситроен, и заехали в Теслу просто потому, что она была рядом. Но нас купили на блестяшки.
Есть плюсы и минусы. Дело вкуса, как мне кажется. Но водителю особо не стоит управлять на ходу. И голосовое управление у теслы понимало даже мой ломаный французский.
3) Вертикальные боковые двери. Одна мысль — будущее наступило. Дети будут в восторге + всегда можно открыть двери не беспокоясь о слишком высоком бардюре


Ребенок потом 2 дня только про двери и говорил, это да )
Но иногда они неудобны. Если в подземной парковке очень низкий потолок (в Париже такое сплошь и рядом), то двери открываются не полностью. Ничего особо критичного, но не очень удобно.
S, X надо брать 100 кВт и это уже совсем другие деньги.
Зарядок оказалось в шаговой доступности от дома 4 штуки. Но пока все чисто в теории, будем на собственных ошибках учиться.
Гибрид не хочется принципиально, хотя Volvo очень нравится. Но ДВС больше вообще не прельщает. Возможно, временно )).
Детей двое, но места в машине действительно очень много, в том числе в S. И очень большой багажник. Маршруты по европе мы прокладывали из встроенной навигации. Она показывает где по дороге заряжаться и сколько займет времени зарядка. Полная зарядка на суперчарджере — это 40 минут для 100 кВт машины, 30 минут для 75 кВт. Этого хватает на 300-400 км трассы, в зависимости от. Рискнем.
Но гибрид в этом плане выглядит безопаснее, согласен с Вами.
Пока думаем, все же, покупка не дешевая, хотя финансирование тут очень доступное. Но, скорее всего, да.
Вроде гик-мобиль, но Вы ставьте минус, если считаете, что этому не место тут. Иначе, как понять.
Там тесла родстер старая. 100 кВт только в последних Х/S. В старом родстере дай бог 50, скорее — еще сильно меньше.
Плюс, он старый, соответственно ресурс его уже не тот, что был раньше. Ну и космос… Может, и действительно его задействовали.
само собой. 2 недели гиктаймс статьями мучал.
Юнити в то время был ещё не торт.
Ну и, как я написал выше, мне было просто интересно писать движок.
Мне было интересно писать именно движок. Я по натуре не игродел, наверное )
Но, думаю, вы правы.
На андроид, к сожалению, пороха не хватило. Хотя порт должен быть довольно простым, по идее, если делать через NDK
А в Париже снегопад. Очень редкое и очень радостное явление. Весь город в снегу!
Спасибо.
Действительно, совершенно забыл рассказать про AI. Правда, ничего особо интересного в нем нет, просто машина состояний. Единая для всех врагов. Враг перед ходом оценивает свое здоровье, сколько его сторонников рядом и сколько противников рядом, и либо атакует, либо бежит к ближайшему стороннику.
Высокоуровневые противники могу отправлять сообщение на сбор всех на подмогу, тогда низкоуровневые бросают все и бегут к высокоуровневому.
В общем, все довольно примитивно, и было написано довольно быстро.
Только листинг функции очень обьемный ))

По музыке, к сожалению, не подскажу, ей занимались Федор Михалыч и Димон.

Большой и страшненький кусок кода
void agProcessAI() {
    int friendsnear;//, foesnear; - self.visibleenemiescount
    int closestfoe, closestfriend, closestvisiblefoe;
    int closestfoedistance, closestfrienddistance, closestvisiblefoedistance;
    int proceedfalg;
    int currmodelnum;
    int unitsAlive = 0;
    // if there are animations, we do not proceed
    // we check if there are any active animations, like running or shooting
    proceedfalg = LEAF_YES;
    for (int i=0; i<agVars.enemyUnitsCount; i++) {
        // wait for ongoing animations to finish
        if(
           (agVars.enemyUnits[i].model.currAnimation != ANIMSTAND) &&
           (agVars.enemyUnits[i].model.currAnimation != ANIMSIT) &&
           (agVars.enemyUnits[i].model.currAnimation != ANIMDEAD)
           )
        {
            proceedfalg = LEAF_NO;
#ifdef DEBUGACTIONGAME
            leafLog(LEAF_NO, "AG: agProcessAI: waiting for enemyUnit[%i] to finish animation %i\n", i, agVars.enemyUnits[i].model.currAnimation);
#endif
        }
        if(agVars.enemyUnits[i].health > 0) {
            unitsAlive++;
        }
    }
    // if there are animations, finish method.
    if(!proceedfalg) {
        return;
    }
    // and if there are no active animations, we are free to act next
    // do some thinking
    switch (agVars.aiState) {
            
        case LEAFAIGLOBALSTATEINIT:
            // we need to reset any AI info left from previous turn
            for(int i=0; i<agVars.enemyUnitsCount; i++) {
                //agVars.enemyUnits[i].aiInbox = AIMESSAGENOMESSAGES;
                agVars.enemyUnits[i].aiState = LEAFAIACTIONINIT;
                agGetVisibilityFor(&agVars.enemyUnits[i], agVars.playerUnits, agVars.playerUnitsCount);
            }
            agVars.aiState = LEAFAIGLOBALACTION;
            //break;  // GLOBAL AI INIT - no need to break, we are ok to proceed with ACTION
        
        case LEAFAIGLOBALACTION:
            // main part. We check every model's AI state and do something
            // find first model to work on
            currmodelnum = -1;
            for(int i=0; i<agVars.enemyUnitsCount; i++) {
                if(agVars.enemyUnits[i].aiState != LEAFAIACTIONENDMOVE) {
                    currmodelnum = i;
                    break;
                }
            }
#ifdef DEBUGACTIONGAME
            leafLog(LEAF_NO, "AG: AI: ******\nprocessing enemy %i\n*******\n", currmodelnum);
#endif
            if(currmodelnum < 0) {// if there are no models to work on, set turn completion flag and return
#ifdef DEBUGACTIONGAME
                leafLog(LEAF_NO, "AG: AI: Done all, finishing\n");
#endif
                agVars.aiState = LEAFAIGLOBALCOMPLETED;
                return;
            }
            // check if we are alive
            if((agVars.enemyUnits[currmodelnum].health > 0) &&
               (agVars.enemyUnits[currmodelnum].TUs > 0) &&
               (agVars.enemyUnits[currmodelnum].aiState != LEAFAIACTIONENDMOVE))  // alive, has TUs and needs processing
            {
                // GET some location info...
#ifdef DEBUGACTIONGAME
                leafLog(LEAF_NO, "AG: AI: desciding what to do for enemy %i\n", currmodelnum);
#endif
                // first we findout how many friends and foes do we see
                friendsnear = 0;
                //foesnear = 0;
                agVars.enemyUnits[currmodelnum].visibleEnemiesCount = 0;
                closestfriend = -1;
                closestfoe = -1;
                closestvisiblefoe = -1;
                closestfoedistance = GAMEVIEWDISTSQARED*GAMEVIEWDISTSQARED;
                closestfrienddistance = GAMEVIEWDISTSQARED*GAMEVIEWDISTSQARED;
                closestvisiblefoedistance = GAMEVIEWDISTSQARED*GAMEVIEWDISTSQARED;
                for(int ii=0; ii<agVars.enemyUnitsCount; ii++) {
                    if((agVars.enemyUnits[ii].health > 0) && (ii != currmodelnum)) {  // if alive and not self
                        int distance = (int)agGetDistanceSQ(&agVars.enemyUnits[currmodelnum], &agVars.enemyUnits[ii]);
                        if(distance < closestfrienddistance) {
                            // this is closest friend so far
                            closestfrienddistance = distance;
                            closestfriend = ii;
                        }
                        if(distance < GAMEVIEWDISTSQARED) {
                            friendsnear++;
                        }
                    }// if alive
                }// for enemycount
                for(int ii=0; ii<agVars.playerUnitsCount; ii++) {
                    if(agVars.playerUnits[ii].health > 0) {
                        int distance = (int)agGetDistanceSQ(&agVars.enemyUnits[currmodelnum], &agVars.playerUnits[ii]);
                        if(distance < closestfoedistance) {
                            // this is closest foe so far
                            closestfoedistance = distance;
                            closestfoe = ii;
                            // can we see this foe?
                            if(agIsVisibleFor(&agVars.enemyUnits[currmodelnum], &agVars.playerUnits[ii])) {
                                agVars.enemyUnits[currmodelnum].visibleEnemiesCount++;
                                if(distance < closestvisiblefoedistance) {
                                    closestvisiblefoedistance = distance;
                                    closestvisiblefoe = ii;
                                }
                            }
                        }
                        /*
                        if(distance < GAMEVIEWDISTSQARED) {
                            agVars.enemyUnits[currmodelnum].visibleEnemiesCount++;
                        }
                         */
                    }// if alive
                }// for modelcount
#ifdef DEBUGACTIONGAME
                leafLog(LEAF_NO, "AG: AI: see %i friends and %i foes\n", friendsnear, agVars.enemyUnits[currmodelnum].visibleEnemiesCount);
#endif
                // what state are we in?
                switch (agVars.enemyUnits[currmodelnum].aiState) {
                        
                    case LEAFAIACTIONINIT:
                        // what to do?
//************************************************************************************
						// check messages
                        if(agVars.enemyUnits[currmodelnum].aiInbox != AIMESSAGENOMESSAGES) {
                            agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONCHECKMESSAGES;
                            return;
                        }
                        // call to arms?
                        if( (agVars.enemyUnits[currmodelnum].visibleEnemiesCount) && (enemy[agVars.enemyUnits[currmodelnum].type].callToArmsDistanceSQ > SMALLNUMBER) ) {
                            for(int i=0; i<agVars.enemyUnitsCount; i++) {
                                if(i == currmodelnum) {
                                    continue;
                                }
                                // check if a callee is close enough
                                if(agGetDistanceSQ(&agVars.enemyUnits[currmodelnum], &agVars.enemyUnits[i]) < enemy[agVars.enemyUnits[currmodelnum].type].callToArmsDistanceSQ) {
                                    agVars.enemyUnits[i].aiInbox = AIMESSAGECALLTOARMS;
                                    agVars.enemyUnits[i].aiSender = currmodelnum;
#ifdef DEBUGACTIONGAME
                                    agPrintToInfoboard(getLocalizedString("DE7"));
#endif
                                }
                            }
                        }
//************************************************************************************
                        // am I the last man standing?
                        if(unitsAlive < 2) {
#ifdef DEBUGACTIONGAME
                            leafLog(LEAF_NO, "AG: AI: I am the last man standing.... BERSERK\n");
                            agPrintToInfoboard(getLocalizedString("DE8"));
#endif
                            agVars.enemyUnits[currmodelnum].aiState = LEAFAIBERSERK;
                            return;

                        }
                        // if there are no foes near...
                        if(agVars.enemyUnits[currmodelnum].visibleEnemiesCount == 0) {
                            // if the closest enemy is very far, do nothing
                            if(closestfoedistance > (int)((float)GAMEVIEWDISTSQARED*GAMEPERCEPTIONDISTANCE)) {
#ifdef DEBUGACTIONGAME
                                leafLog(LEAF_NO, "AG: AI: enemies far, do nothing\n");
#endif
                                agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONDONOTHING;
                                return;
                            } else {   // closest enemy is close enough to think...
                                // if there is more then 1 friend arround, and we have TUs to FIRE, we try to come closer to the enemy
                                if( (friendsnear > 1) && (agVars.enemyUnits[currmodelnum].TUs > TUCOSTFIRE) ) {
#ifdef DEBUGACTIONGAME
                                    leafLog(LEAF_NO, "AG: AI: enemies far, but friends arround. I'll try to come closer to my closest enemy\n");
#endif
                                    agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONCOMECLOSER;
                                    return;
                                } else {// if there are no friends arround, or we do not have enough TUs to fire
#ifdef DEBUGACTIONGAME
                                    leafLog(LEAF_NO, "AG: AI: enemies far, no friends arround, i'll stay here\n");
#endif
                                    agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONDONOTHING;
                                    return;
                                }
                            }// enemies close enough but unseen
                        }// no foes near
                        else {   // there are foes near
                            // and there are friends arround
                            if(friendsnear > 0) {
                                // if we are OK on health, come closer and attack
                                if(agVars.enemyUnits[currmodelnum].health > AIHEALTHLOW) {
#ifdef DEBUGACTIONGAME
                                    leafLog(LEAF_NO, "AG: AI: i have a lot of health, i'll come closer and attack\n");
#endif
                                    agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONCOMEANDFIRE;
                                    return;
                                } else {    // health low, run away
#ifdef DEBUGACTIONGAME
                                    leafLog(LEAF_NO, "AG: AI: health low, running away\n");
#endif
                                    agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONRUNAWAY;
                                    return;
                                }
                            }// foes near, friends near
                            else {   //no friends near
                                // if there are more then 2 foes and no friends, run away
                                if(/*foesnear*/agVars.enemyUnits[currmodelnum].visibleEnemiesCount > 2) {
#ifdef DEBUGACTIONGAME
                                    leafLog(LEAF_NO, "AG: AI: no friends arround, too many foes, running away\n");
#endif
                                    agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONRUNAWAY;
                                    return;
                                } else {   // less then 2 foes and no friends
                                    // if there is enough health, attack
                                    if(agVars.enemyUnits[currmodelnum].health > AIHEALTHLOW) {
#ifdef DEBUGACTIONGAME
                                        leafLog(LEAF_NO, "AG: AI: no friends, less then 2 foes, but health ok, attacking\n");
#endif
                                        agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONFIRENOW;
                                        return;
                                    } else {   // health problems, run away
#ifdef DEBUGACTIONGAME
                                        leafLog(LEAF_NO, "AG: AI: no friends, less then 2 foes, low health -> running away\n");
#endif
                                        agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONRUNAWAY;
                                        return;
                                    }
                                }// no friends and less then 2 foes
                            }// foes near, no friends near
                        }// foes near
                        break;  // LEAFAIACTIONINIT
                        
                    case LEAFAIACTIONFIRENOW:
                        // is enemy visible?
                        if(!agIsGloballyVisible((int)agVars.enemyUnits[currmodelnum].x, (int)agVars.enemyUnits[currmodelnum].z)) {
#ifdef DEBUGACTIONGAME
                            leafLog(LEAF_NO, "AG: AI: i see enemies, but i am invisible, i will do nothing\n");
#endif
                            agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONDONOTHING;
                            return;
                        }
                        // if we can, fastsit!
                        if((agVars.enemyUnits[currmodelnum].skills & skills[SKILLFASTSIT]) && (!agVars.enemyUnits[currmodelnum].isSitting))
                        {
#ifdef DEBUGACTIONGAME
                            leafLog(LEAF_NO, "AG: AI: Can sit!\n");
#endif
                            agVars.enemyUnits[currmodelnum].isSitting = LEAF_YES;
                            md2ChangeAnimation(&agVars.enemyUnits[currmodelnum].model, ANIMSITDN, agVars.currTime);
                            return;
                        }
                        // before firing, we need to make sure there are visible foes, and shoot them only!
                        if(closestvisiblefoe >= 0) {
                            agAIFire(&agVars.enemyUnits[currmodelnum], &agVars.playerUnits[closestvisiblefoe]);
                        } else {
                            // there are no visible foes, what do we do????
                            // we're either already came closer, or we cannot...
                            // so we pass
                            agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONDONOTHING;
                        }
                        break;// LEAFAIACTIONEFIRENOW
                        
                    case LEAFAIBERSERK:
                        // this happens when there's only one enemyunit left on the map.
                        // right now it will act as if it recieved LEAFAIACTIONCOMEANDFIRE
                        agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONCOMEANDFIRE;
                        break; // LEAFAIBERSERK
                        
                    case LEAFAIACTIONCOMEANDFIRE:
                        agAIComeCloser(&agVars.enemyUnits[currmodelnum], (int)agVars.playerUnits[closestfoe].x, (int)agVars.playerUnits[closestfoe].z, TUCOSTFIRE, LEAFAIACTIONINIT);
                        agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONFIRENOW;
                        break;// LEAFAIACTIONCOMEANDFIRE
                        
                    case LEAFAIACTIONCOMECLOSER:
                        agVars.enemyUnits[currmodelnum].aiState = agAIComeCloser(&agVars.enemyUnits[currmodelnum], (int)agVars.playerUnits[closestfoe].x, (int)agVars.playerUnits[closestfoe].z, TUCOSTFIRE, LEAFAIACTIONINIT);
                        break;// LEAFAIACTIONCOMECLOSER
                        
                    case LEAFAIACTIONRUNAWAY:
                        // same as walk closer, but walking closer to nearest friend
                        // if there are any TUs, we run!
                        if(agVars.enemyUnits[currmodelnum].TUs > 0) {
                            // will run away if there is a friend to run to. If left alone, fight!
                            if(closestfriend < 0) {
#ifdef DEBUGACTIONGAME
                                leafLog(LEAF_NO, "AG: AI: Want to run away, but no friends near.\n");
#endif
                                if(agVars.enemyUnits[currmodelnum].TUs >= TUCOSTFIRE) {
#ifdef DEBUGACTIONGAME
                                    leafLog(LEAF_NO, "AG: AI: No friends to run to but have TUs to fire!\n");
#endif
                                    agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONFIRENOW;
                                    return;
                                }// have TUs to fire
                                else {
#ifdef DEBUGACTIONGAME
                                    leafLog(LEAF_NO, "AG: AI: No friends to run to and no TUs to fire.. Staying here.\n");
#endif
                                    agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONDONOTHING;
                                    return;
                                }// no TUs to fire
                            }// there are no friends close
                            agVars.enemyUnits[currmodelnum].aiState = agAIComeCloser(&agVars.enemyUnits[currmodelnum], (int)agVars.enemyUnits[closestfriend].x, (int)agVars.enemyUnits[closestfriend].z, TUCOSTAUTOFIRE, LEAFAIACTIONFIRENOW);
                        }
                        break;// LEAFAIACTIONRUNAWAY
                        
                    case LEAFAIACTIONDONOTHING:
                        // if unit has FASTSIT skill, we sit it down
                        if(agVars.enemyUnits[currmodelnum].health > 0) {
                            if((agVars.enemyUnits[currmodelnum].skills & skills[SKILLFASTSIT]) && (!agVars.enemyUnits[currmodelnum].isSitting) )
                            {
                                agVars.enemyUnits[currmodelnum].isSitting = LEAF_YES;
                                md2ChangeAnimation(&agVars.enemyUnits[currmodelnum].model, ANIMSITDN, agVars.currTime);
                                break;
                            } else {
                                // now it has nothing to do and sits, if it has fastsit
                                // we check for any RELEASED hostages we can kill and shoot them, if we can.
                                if(agVars.enemyUnits[currmodelnum].TUs >= TUCOSTFIRE) {
                                    for(int k=0; k<agVars.hostageUnitsCount; k++) {
                                        if( (agVars.hostageUnits[k].health > 0) && (agVars.hostageUnits[k].aiState == LEAFAIHOSTAGERELEASED) )
                                        {
                                            if(agIsVisibleFor(&agVars.enemyUnits[currmodelnum], &agVars.hostageUnits[k])) {
#ifdef DEBUGACTIONGAME
                                                leafLog(LEAF_NO, "AG: AI: Nothing to do, but i see a released hostage to kill.\n");
#endif
                                                agAIFire(&agVars.enemyUnits[currmodelnum], &agVars.hostageUnits[k]);
                                                agVars.enemyUnits[currmodelnum].TUs -= TUCOSTFIRE;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        // Then we are done
                        agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONENDMOVE;
                        break;
                        
//************************************************************************************
                        
                    case LEAFAIACTIONCHECKMESSAGES: {
#ifdef DEBUGACTIONGAME
                        leafLog(LEAF_NO, "AG: AI: in LEAFAIACTIONCHECKMESSAGES\n");
#endif
                        switch(agVars.enemyUnits[currmodelnum].aiInbox) {
                            case AIMESSAGECALLTOARMS:
                                // FIRST OF ALL!!! clear message
                                agVars.enemyUnits[currmodelnum].aiInbox = AIMESSAGENOMESSAGES;
                                // go to sender
                                if(agVars.enemyUnits[currmodelnum].TUs > 0) {
#ifdef DEBUGACTIONGAME
                                    leafLog(LEAF_NO, "AG: AI: recieved CALLTOARMS from %i, going to: %i:%i to %i:%i\n", agVars.enemyUnits[currmodelnum].aiSender, (int)agVars.enemyUnits[currmodelnum].x, (int)agVars.enemyUnits[currmodelnum].z, (int)agVars.enemyUnits[agVars.enemyUnits[currmodelnum].aiSender].x, (int)agVars.enemyUnits[agVars.enemyUnits[currmodelnum].aiSender].z);
#endif
                                    // if sender is close enough, ignore
                                    if(agGetDistanceSQ(&agVars.enemyUnits[agVars.enemyUnits[currmodelnum].aiSender], &agVars.enemyUnits[currmodelnum]) <= 9)
                                    {
#ifdef DEBUGACTIONGAME
                                        leafLog(LEAF_NO, "AG: AI: I am too close to come closer to sender. On my own now.\n");
#endif
                                        // reinit AI.
                                        agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONINIT;
                                        return;
                                    }
                                    agVars.enemyUnits[currmodelnum].aiState = agAIComeCloser(&agVars.enemyUnits[currmodelnum], (int)agVars.enemyUnits[agVars.enemyUnits[currmodelnum].aiSender].x, (int)agVars.enemyUnits[agVars.enemyUnits[currmodelnum].aiSender].z, TUCOSTFIRE, LEAFAIACTIONINIT);
                                }// enough TUs to come closer
                                else {   // no enough TUs to come closer
#ifdef DEBUGACTIONGAME
                                    leafLog(LEAF_NO, "AG: AI: No TUs to come closer. I'll do nothing\n");
#endif
                                    agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONDONOTHING;
                                    return;
                                }
                                break;// AIMESSAGECALLTOARMS
                                
                            default:
#ifdef DEBUGACTIONGAME
                                leafLog(LEAF_NO, "AG: AI: Unknown message!!!\n");
#endif
                                agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONINIT;
                                break;
                        }
                    } break;// LEAFAIACTIONCHECKMESSAGES
                        
//************************************************************************************
                        
                    default:
#ifdef DEBUGACTIONGAME
                        leafLog(LEAF_NO, "AG: AI: Unknow AI state in EnemyLogic for enemy %i\n", currmodelnum);
#endif
                        agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONENDMOVE;
                        return;
                        break;
                }// switch currmodel->AIstate
            }// alive and has TUs
            else {// dead and/or has no TUs
                agVars.enemyUnits[currmodelnum].aiState = LEAFAIACTIONENDMOVE;
                return;
            }// dead and/or has no TUs
            break;  // GLOBAL AI ACTION
            
        case LEAFAIGLOBALCOMPLETED: {// finish turn
            // but first...
            // we will check if there are units who have a lot of unused TUs
            // if there are other units not far who see enemies, we move those units to support them
            int noFurtherMoves = LEAF_YES;
            for(int i=0; i<agVars.enemyUnitsCount; i++) {
                if(agVars.enemyUnits[i].health < AGAIHEALTHTOHELP) {
                    continue;
                }
                if(enemy[agVars.enemyUnits[i].type].helpDistanceSQ < SMALLNUMBER) { // 0.0f for units who don't run to help
                    continue;
                }
                if(agVars.enemyUnits[i].TUs > AGAITUSTOMOVETOHELP) {
                    // enough TUs. Let's see if there are units around who see eneies
                    float closestUnitSQ = GAMEVIEWDISTSQARED*2;// too far to start with
                    int helpeeIndex = -1;
                    for(int k=0; k<agVars.enemyUnitsCount; k++) {
                        // if self, skip
                        if(i==k) {
                            continue;
                        }
                        // is the new unit seeing enemy
                        if(agVars.enemyUnits[k].visibleEnemiesCount > 0) {
                            // is unit close enough? is unit far enough? (Maybe we're already there)
                            float newDistance = agGetDistanceSQ(&agVars.enemyUnits[i], &agVars.enemyUnits[k]);
                            if((newDistance < enemy[agVars.enemyUnits[i].type].helpDistanceSQ) && (newDistance > 1.0f-SMALLNUMBER)) {
                                // do we already know a unit who needs help and is closer
                                if( (helpeeIndex == -1) || (closestUnitSQ > newDistance) ) {
                                    helpeeIndex = k;
                                    closestUnitSQ = newDistance;
                                }// found new helpee
                            }// found close helpee
                        }// found helpee
                    } // for all helpees
                    if(helpeeIndex > -1) {
#ifdef DEBUGACTIONGAME
                        leafLog(LEAF_NO, "AG: AI: enemy %i is rushing to help enemy %i\n", i, helpeeIndex);
                        agPrintToInfoboard(getLocalizedString("DE6"));
#endif
                        agVars.enemyUnits[i].aiState = agAIComeCloser(&agVars.enemyUnits[i], (int)agVars.enemyUnits[helpeeIndex].x, (int)agVars.enemyUnits[helpeeIndex].z, TUCOSTAUTOFIRE, LEAFAIACTIONINIT);
                        // is there a path at all?
                        if(agVars.enemyUnits[i].aiState != LEAFAIACTIONDONOTHING) {
                            noFurtherMoves = LEAF_NO;
                            agVars.aiState = LEAFAIGLOBALACTION;
                            break;
                        }
                    }
                }// if helper has enough TUs
            }// for all helpers
            if(noFurtherMoves) {
                agChangeTurn(TURNHOSTAGES);
            }
        } break;  // GLOBAL AI COMPLETED
            
        default:
            break;
    }// switch global AIstate
}// agProcessAI

Великолепная статья, спасибо!
Не хотел, чтобы статью сочли рекламной.
Но игра бесплатна уже, без встроенной рекламы и встроенных покупок… так что, наверное, можно?

eggsodus
мне стыдно этот код выкладывать. Честно, не жалко, а стыдно ))
Ну, опыт получен, игра в аппсторе лежит… Я считаю, это хэппи энд. А всех денег не заработать.

Information

Rating
Does not participate
Location
Paris, Paris, Франция
Registered
Activity