package shot import ( "strconv" "strings" "time" . "wartank/app/lev0/types" "wartank/app/lev1/shot/damage" "wartank/app/lev1/shot/shot_time" // "wartank/internal/components/sound" "wartank/app/lev0/alias" . "gitp78su.ipnodns.ru/svi/kern" . "gitp78su.ipnodns.ru/svi/kern/kc/helpers" . "gitp78su.ipnodns.ru/svi/kern/krn/ktypes" ) /* Исходник предоставляет выстрел со свойствами: - время до выстрела - длительность перезарядки Первый параметр постоянно изменяется (после выстрела восстанавливается) Второй параметр меняется медленно (в зависимости от количества очков после выстрела) */ // выстрел -- объект выстрела type выстрел struct { ИСражениеПроцесс // FIXME: перезарядка *shot_time.ShotTime // Сколько времени нужно для полной перезарядки урон *damage.Damage // Урон от выстрела с памятью уронВсего alias.АУрон // Суммарный урон isEnd ISafeBool // Признак конца сражения еслиБлок ISafeBool // Признак блокировки выстрела логин string // Логин для поиска контрольных строк chTick chan int // Тик для выстрела } // НовВыстрел -- возвращает новый выстрел func НовВыстрел(проц ИСражениеПроцесс) ИВыстрел { Hassert(проц != nil, "НовВыстрел(): ИСражениеПроцесс == nil") логинТанк := проц.Бот().Имя() сам := &выстрел{ ИСражениеПроцесс: проц, перезарядка: shot_time.NewShotTime(), урон: damage.NewDamage(), еслиБлок: NewSafeBool(), isEnd: проц.ЕслиКонец(), логин: логинТанк, chTick: make(chan int, 2), } // Установить время перезарядки сам.перезарядка.Set(6800) go сам.makeTick() go сам.run() return сам } // БлокУст -- установка блокировки выстрела func (сам *выстрел) БлокУст() { сам.еслиБлок.Set() } // БлокСброс -- сброс блокировки выстрела func (сам *выстрел) БлокСброс() { сам.еслиБлок.Reset() } // ЕслиБлок -- возвращает признак блокировки выстрела func (сам *выстрел) ЕслиБлок() bool { return сам.еслиБлок.Get() } // Генерирует тики, когда можно стрелять func (сам *выстрел) makeTick() { defer func() { сам.isEnd.Set() close(сам.chTick) сам.Отменить() // log._rintf("Shot.makeTick(): сражение завершёно\n") }() countMasking := 0 for { select { case <-сам.Контекст().Done(): return default: if сам.isEnd.Get() { // Битва закончилась return } switch сам.еслиБлок.Get() { // Проверить запрет на стрельбу при слабом здоровье case true: // log._rintf("WARN Shot.run(): запрет на выстрел\n") countMasking++ if countMasking >= 200 { return } сам.Манёвр() time.Sleep(time.Millisecond * 500) continue default: countMasking = 0 } сам.chTick <- 1 // Здесь же первый выстрел recharge := сам.перезарядка.Get() // log._rintf("INFO Shot.run() перезарядка=%v msec\n", recharge) // Если идёт перезарядка -- постепенно обнуляем время ожидания time.Sleep(time.Millisecond * time.Duration(recharge)) } } } // Цикл выстрела (в отдельном потоке) func (сам *выстрел) run() { for { select { case <-сам.Контекст().Done(): return case <-сам.chTick: // Стрелять можно, стандартное ожидание сам.shot() сам.findDamage() } } } // Обновляет возможность выстрела (~) // // Вызывается из отдельного потока func (сам *выстрел) shot() { сам.Обновить() var ( strOut string lstBattle = сам.СписПолучить() еслиНайдено bool err error ) // ОБЫЧНЫЕ for _, strOut = range lstBattle { if strings.Contains(strOut, `-currentControl-attackRegularShellLink`) { еслиНайдено = true break } } if !еслиНайдено { // log._rintf("WARN Shot.shot(): не найдены ссылка на выстрел\n") сам.isEnd.Set() сам.Бот().КонтБот().Cancel() return } strLink := strings.TrimPrefix(strOut, `ОБЫЧНЫЕ`) strLink = "https://wartank.ru/" + strLink lstBattle, err = сам.Сеть().Get(strLink) if err != nil { // log._rintf("ERRO Shot.shot(): при исполнении GET-команды выстрела обычным снарядом, err=\n\t%v\n", err) сам.isEnd.Set() сам.Бот().КонтБот().Cancel() return } сам.СтрОбновить(lstBattle) // sound.Shot() сам.Манёвр() } // Ищет урон от выстрела func (сам *выстрел) findDamage() { var ( ind int еслиНайдено bool lstShot = сам.СписПолучить() strOut string ) for ind, strOut = range lstShot { // prospero tank if strings.Contains(strOut, ``+сам.логин+``) { ind += 2 strOut = lstShot[ind] еслиНайдено = true break } } if !еслиНайдено { // Возможно был рикошет или манёвр // log._rintf("WARN Shot.findDamage(): не найден урон от выстрела, strOut=%q, ind=%v\n", strOut, ind) return } lstDamage := strings.Split(strOut, ` на `) if len(lstDamage) == 1 { return } strDamage := lstDamage[1] iDamage, err := strconv.Atoi(strDamage) if err != nil { // log._rintf("ERRO Shot.findDamage(): damage(%v) не число, err=\n\t%v\n", strDamage, err) return } if iDamage <= 0 { // Кривой урон от выстрела сам.перезарядка.Dec5() // log._rintf("WARN Shot.findDamage(): ошибка в значении урона(%v)\n", iDamage) iDamage = 0 } сам.уронВсего += alias.АУрон(iDamage) // log._rintf("INFO Shot.Damage(): damageSum=%v\n", сам.damageSum) if iDamage < 70 { сам.урон.Set(alias.АУрон(iDamage)) сам.перезарядка.Inc210() } // log._rintf("INFO Shot.findDamage(): выстрел=+%v, урон=%v", iDamage, сам.damageSum) if iDamage == 0 { return } сам.setDamage(alias.АУрон(iDamage)) } // setDamage -- обновляет время перезарядки в зависимости от произведённого урона func (сам *выстрел) setDamage(val alias.АУрон) { сам.урон.Set(val) switch сам.урон.Result() { case "none": сам.перезарядка.Dec5() case "up": сам.перезарядка.Dec30() case "down": сам.перезарядка.Inc210() } } // IsEnd -- возвращает объект разрешения стрельбы func (сам *выстрел) IsEnd() ISafeBool { return сам.isEnd }