Мне вот салон 3ки безумно понравился на картинках. В живую их не найти. Очередь тут на конец 2019го.
Х наворочен и поэтому немного обидно, что С, которая попроще, стоит столько же, если батарейка одинаковая с Х. То есть, создается впечатление, что, покупая С, ты платишь столько же, а получаешь меньше, чем Х.
Но в итоге нам С тоже понравилась больше.
И да, на 75 кВт батарейке Х все же прилично меньше, чем С проедет, а 100 кВт сильно дороже.
Я, наверное, непонятно написал. Речь о парковке, когда надо руль постоянно крутить от упора до упора, на маленькой скорости или на месте. Такое ощущение, что жгут наматываешь, не особо приятно.
Совершенно с Вами согласен, и те же мысли не дают покоя. Но машина нужна сейчас.
Вначале думали взять подержаный Ситроен, и заехали в Теслу просто потому, что она была рядом. Но нас купили на блестяшки.
Есть плюсы и минусы. Дело вкуса, как мне кажется. Но водителю особо не стоит управлять на ходу. И голосовое управление у теслы понимало даже мой ломаный французский.
3) Вертикальные боковые двери. Одна мысль — будущее наступило. Дети будут в восторге + всегда можно открыть двери не беспокоясь о слишком высоком бардюре
Ребенок потом 2 дня только про двери и говорил, это да )
Но иногда они неудобны. Если в подземной парковке очень низкий потолок (в Париже такое сплошь и рядом), то двери открываются не полностью. Ничего особо критичного, но не очень удобно.
S, X надо брать 100 кВт и это уже совсем другие деньги.
Зарядок оказалось в шаговой доступности от дома 4 штуки. Но пока все чисто в теории, будем на собственных ошибках учиться.
Гибрид не хочется принципиально, хотя Volvo очень нравится. Но ДВС больше вообще не прельщает. Возможно, временно )).
Детей двое, но места в машине действительно очень много, в том числе в S. И очень большой багажник. Маршруты по европе мы прокладывали из встроенной навигации. Она показывает где по дороге заряжаться и сколько займет времени зарядка. Полная зарядка на суперчарджере — это 40 минут для 100 кВт машины, 30 минут для 75 кВт. Этого хватает на 300-400 км трассы, в зависимости от. Рискнем.
Но гибрид в этом плане выглядит безопаснее, согласен с Вами.
Там тесла родстер старая. 100 кВт только в последних Х/S. В старом родстере дай бог 50, скорее — еще сильно меньше.
Плюс, он старый, соответственно ресурс его уже не тот, что был раньше. Ну и космос… Может, и действительно его задействовали.
Спасибо.
Действительно, совершенно забыл рассказать про 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
Х наворочен и поэтому немного обидно, что С, которая попроще, стоит столько же, если батарейка одинаковая с Х. То есть, создается впечатление, что, покупая С, ты платишь столько же, а получаешь меньше, чем Х.
Но в итоге нам С тоже понравилась больше.
И да, на 75 кВт батарейке Х все же прилично меньше, чем С проедет, а 100 кВт сильно дороже.
Вначале думали взять подержаный Ситроен, и заехали в Теслу просто потому, что она была рядом. Но нас купили на блестяшки.
Ребенок потом 2 дня только про двери и говорил, это да )
Но иногда они неудобны. Если в подземной парковке очень низкий потолок (в Париже такое сплошь и рядом), то двери открываются не полностью. Ничего особо критичного, но не очень удобно.
Зарядок оказалось в шаговой доступности от дома 4 штуки. Но пока все чисто в теории, будем на собственных ошибках учиться.
Гибрид не хочется принципиально, хотя Volvo очень нравится. Но ДВС больше вообще не прельщает. Возможно, временно )).
Детей двое, но места в машине действительно очень много, в том числе в S. И очень большой багажник. Маршруты по европе мы прокладывали из встроенной навигации. Она показывает где по дороге заряжаться и сколько займет времени зарядка. Полная зарядка на суперчарджере — это 40 минут для 100 кВт машины, 30 минут для 75 кВт. Этого хватает на 300-400 км трассы, в зависимости от. Рискнем.
Но гибрид в этом плане выглядит безопаснее, согласен с Вами.
Плюс, он старый, соответственно ресурс его уже не тот, что был раньше. Ну и космос… Может, и действительно его задействовали.
Ну и, как я написал выше, мне было просто интересно писать движок.
Но, думаю, вы правы.
Действительно, совершенно забыл рассказать про AI. Правда, ничего особо интересного в нем нет, просто машина состояний. Единая для всех врагов. Враг перед ходом оценивает свое здоровье, сколько его сторонников рядом и сколько противников рядом, и либо атакует, либо бежит к ближайшему стороннику.
Высокоуровневые противники могу отправлять сообщение на сбор всех на подмогу, тогда низкоуровневые бросают все и бегут к высокоуровневому.
В общем, все довольно примитивно, и было написано довольно быстро.
Только листинг функции очень обьемный ))
По музыке, к сожалению, не подскажу, ей занимались Федор Михалыч и Димон.
Но игра бесплатна уже, без встроенной рекламы и встроенных покупок… так что, наверное, можно?
eggsodus