package health import ( "strconv" "strings" "time" . "wartank/app/lev0/types" "wartank/app/lev1/health/health_time" "wartank/app/lev1/repair_time" // "wartank/internal/components/sound" . "gitp78su.ipnodns.ru/svi/kern" . "gitp78su.ipnodns.ru/svi/kern/kc/helpers" . "gitp78su.ipnodns.ru/svi/kern/krn/ktypes" ) /* Контролирует состояние здоровья танка */ // Здоровье -- контроль здоровья танка type Здоровье struct { ИСражениеПроцесс // FIXME: здоровьеСейчас *health_time.HealthTime // Изменяемое здоровье танка здоровьеПолное *health_time.HealthTime // Полное здоровье танка еслиНадо ISafeBool // Необходимость восстановления отсчётАптечка *repair_time.RepairTime // Время до восстановления isEnd ISafeBool // Ссылка на признак конца сражения логин string // Для поиска контрольных строк chTick chan int // Канал для ровной отправки тиков // deltaOld int // Старая дельта потери здоровья // countLow int } // НовЗдоровье -- возвращает новый *Health func НовЗдоровье(проц ИСражениеПроцесс) *Здоровье { Hassert(проц != nil, "НовЗдоровье(): ИСражениеПроцесс == nil") логин := проц.Бот().Имя() сам := &Здоровье{ ИСражениеПроцесс: проц, здоровьеСейчас: health_time.NewHealthTime(), здоровьеПолное: health_time.NewHealthTime(), еслиНадо: NewSafeBool(), отсчётАптечка: repair_time.NewRepairTime(), isEnd: проц.ЕслиКонец(), логин: логин, chTick: make(chan int, 2), } go сам.makeTik() go сам.run() return сам } // Отправляет тики с заданным равным интервалом func (сам *Здоровье) makeTik() { defer func() { close(сам.chTick) сам.Отменить() }() лимитАптечка := 0 // Предел времени ожидания отсчётАптечка := 0 for { select { case <-сам.Контекст().Done(): return default: if сам.ЕслиУбит() { return } if сам.отсчётАптечка.Получ() == отсчётАптечка { лимитАптечка++ } else { отсчётАптечка = сам.отсчётАптечка.Получ() лимитАптечка = 0 } if сам.отсчётАптечка.IsReady() { лимитАптечка = 0 } if лимитАптечка > 90 { return } } сам.chTick <- 1 time.Sleep(time.Second * 1) сам.отсчётАптечка.Dec() } } // Главный цикл обработки здоровья в сражении func (сам *Здоровье) run() { for { select { case <-сам.Контекст().Done(): сам.isEnd.Set() return case <-сам.chTick: сам.здоровьеНайти() сам.найтиВремяВосстановления() if сам.еслиНадо.Get() { go сам.repair() } } } } // Полное -- возвращает объект полного здоровья танка func (сам *Здоровье) Полное() int { return сам.здоровьеПолное.Get() } // ЕслиУбит -- возвращает признак мертвичины танка func (сам *Здоровье) ЕслиУбит() bool { if сам.isEnd.Get() { сам.Отменить() return true } lstBattle := сам.СписПолучить() for _, strOut := range lstBattle { if strings.Contains(strOut, `>Ваш танк подбит.`) { сам.здоровьеСейчас.Set(0) сам.isEnd.Set() сам.Отменить() return true } } return сам.isEnd.Get() } // Ищет время восстановления ремки func (сам *Здоровье) найтиВремяВосстановления() { if сам.отсчётАптечка.IsReady() { return } var ( strOut string lstBattle = сам.СписПолучить() еслиНайдено bool ind int ) // 12 секунд // for ind, strOut = range lstBattle { if strings.Contains(strOut, `ILinkListener-currentControl-repairLink" class="simple-but blue">`) { еслиНайдено = true break } } if !еслиНайдено { return } strOut = lstBattle[ind] // 12 секунд lstTime := strings.Split(strOut, `ILinkListener-currentControl-repairLink" class="simple-but blue">`) if len(lstTime) < 2 { сам.isEnd.Set() сам.Отменить() return } strTime := lstTime[1] strTime = strings.TrimSuffix(strTime, ` секунд`) if err := сам.отсчётАптечка.Уст(strTime); err != nil { сам.isEnd.Set() сам.Отменить() return } } // Восстанавливает здоровье (~) func (сам *Здоровье) repair() { var ( strOut string lstBattleOn = сам.СписПолучить() еслиНайденоRepair bool ind int ) // Ремкомплект // Ремкомплект for ind, strOut = range lstBattleOn { if strings.Contains(strOut, `Ремкомплект`) { еслиНайденоRepair = true break } } if !еслиНайденоRepair { return } strOut = lstBattleOn[ind] // Ремкомплект lstLink := strings.Split(strOut, `Ремкомплект`) strLink = "https://wartank.ru/" + lstLink[0] res := сам.Сеть().Get(strLink) if res.IsErr() { // log._rintf("ERRO Health.repair(): при выполнении GET-команды ремонта, err=\n\t%v\n", res.Error()) сам.isEnd.Set() сам.Отменить() return } lstBattleOn = res.Unwrap() сам.СтрОбновить(lstBattleOn) // sound.Repair() } // Ищет своё здоровье (~) func (сам *Здоровье) здоровьеНайти() { var ( ind int strOut string еслиНайдено bool lstBattle = сам.СписПолучить() ) if len(lstBattle) == 0 { // Принудительно обновим сражение сам.Обновить() lstBattle = сам.СписПолучить() } //
Половина коня
for ind, strOut = range lstBattle { if strings.Contains(strOut, `
`+сам.логин+`"`) { еслиНайдено = true break } } if !еслиНайдено { // Свой танк не найден сам.isEnd.Set() сам.Отменить() return } // Свой танк найден, ищем здоровье //
500
ind += 11 strOut = lstBattle[ind] strHealth := strings.TrimPrefix(strOut, `
`) strHealth = strings.TrimSuffix(strHealth, `
`) iHealth, err := strconv.Atoi(strHealth) if err != nil { сам.isEnd.Set() сам.Отменить() return } сам.здоровьеУстановить(iHealth) } // здоровьеУстановить -- устанавливает текущее здоровье func (сам *Здоровье) здоровьеУстановить(здоровье int) { if здоровье < 0 { // log._rintf("WARN Health.здоровьеУстановить(): кривое значение здоровья танка(%v)\n", val) здоровье = 0 } дельта := сам.здоровьеСейчас.Get() - здоровье if дельта < 0 { // Такое может быть, если было лечение дельта = 0 } if здоровье >= сам.здоровьеПолное.Get() { // log._rintf("WARN Health.здоровьеУстановить(): кривое текущее здоровье, %v/%v\n", val, сам.full.Get()) сам.здоровьеПолное.Set(здоровье) сам.здоровьеСейчас.Set(здоровье) // сам.deltaOld = 0 сам.Выстрел().БлокСброс() сам.еслиНадо.Reset() return } switch { case сам.isEnd.Get(): // Конец сражения сам.здоровьеСейчас.Set(0) сам.isEnd.Set() сам.Отменить() return case здоровье <= 0: // Убит сам.здоровьеСейчас.Set(0) сам.isEnd.Set() сам.Отменить() return case здоровье <= 500: // Запретить стрельбу сам.Выстрел().БлокУст() // Установить запрет стрельбы пока слабое здоровье сам.еслиНадо.Set() сам.Манёвр().УстНадо() case здоровье > 500: // Разрешить стрельбу сам.Выстрел().БлокСброс() сам.еслиНадо.Reset() if дельта > сам.здоровьеПолное.Get()*4/10 { // Проверить на критичность падения здоровья на 40% // log._rintf("WARN Health.здоровьеУстановить(): большая разовая потеря здоровья(%v)\n", delta) сам.Манёвр().УстНадо() сам.еслиНадо.Set() return } } }