| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- package shot
- import (
- "context"
- // "log"
- "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:
- recharge *shot_time.ShotTime // Сколько времени нужно для полной перезарядки
- damage *damage.Damage // Урон от выстрела с памятью
- damageSum alias.АУрон // Суммарный урон
- isEnd ISafeBool // Признак конца сражения
- еслиБлок ISafeBool // Признак блокировки выстрела
- login string // Логин для поиска контрольных строк
- chTick chan int // Тик для выстрела
- ctxEnd context.Context // Признак окончания сражения
- }
- // НовВыстрел -- возвращает новый выстрел
- func НовВыстрел(проц ИСражениеПроцесс) ИВыстрел {
- Hassert(проц != nil, "НовВыстрел(): ИСражениеПроцесс == nil")
- логинТанк := проц.Бот().Имя()
- сам := &выстрел{
- ИСражениеПроцесс: проц,
- ctxEnd: проц.Контекст(),
- recharge: shot_time.NewShotTime(),
- damage: damage.NewDamage(),
- еслиБлок: NewSafeBool(),
- isEnd: проц.ЕслиКонец(),
- login: логинТанк,
- chTick: make(chan int, 2),
- }
- // Установить время перезарядки
- сам.recharge.Set(6800)
- go сам.makeTick()
- go сам.run()
- return сам
- }
- // ЕслиБлок -- возвращает признак блокировки выстрела
- func (сам *выстрел) ЕслиБлок() bool {
- return сам.еслиБлок.Get()
- }
- // Генерирует тики, когда можно стрелять
- func (сам *выстрел) makeTick() {
- defer func() {
- сам.isEnd.Set()
- close(сам.chTick)
- сам.Бот().КонтБот().Cancel()
- // log._rintf("Shot.makeTick(): сражение завершёно\n")
- }()
- countMasking := 0
- for {
- select {
- case <-сам.ctxEnd.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 := сам.recharge.Get()
- // log._rintf("INFO Shot.run() перезарядка=%v msec\n", recharge)
- // Если идёт перезарядка -- постепенно обнуляем время ожидания
- time.Sleep(time.Millisecond * time.Duration(recharge))
- }
- }
- }
- // Цикл выстрела (в отдельном потоке)
- func (сам *выстрел) run() {
- for {
- select {
- case <-сам.ctxEnd.Done():
- return
- case <-сам.chTick:
- // Стрелять можно, стандартное ожидание
- сам.shot()
- сам.findDamage()
- }
- }
- }
- // Обновляет возможность выстрела (~)
- //
- // Вызывается из отдельного потока
- func (сам *выстрел) shot() {
- сам.Обновить()
- var (
- strOut string
- lstBattle = сам.СписПолучить()
- еслиНайдено bool
- err error
- )
- // <a href="pve?6-26.ILinkListener-currentControl-attackRegularShellLink" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>
- for _, strOut = range lstBattle {
- if strings.Contains(strOut, `-currentControl-attackRegularShellLink`) {
- еслиНайдено = true
- break
- }
- }
- if !еслиНайдено {
- // log._rintf("WARN Shot.shot(): не найдены ссылка на выстрел\n")
- сам.isEnd.Set()
- сам.Бот().КонтБот().Cancel()
- return
- }
- lstLink := strings.Split(strOut, `<a href="`)
- strLink := lstLink[1]
- lstLink = strings.Split(strLink, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`)
- strLink = "https://wartank.ru/" + lstLink[0]
- lstBattle, err = сам.Сеть().Get(strLink)
- if err != nil {
- // log._rintf("ERRO Shot.shot(): при исполнении GET-команды выстрела обычным снарядом, err=\n\t%v\n", err)
- сам.isEnd.Set()
- сам.Бот().КонтБот().Cancel()
- return
- }
- if err = сам.СтрОбновить(lstBattle); err != nil {
- // log._rintf("ERRO Shot.shot(): при обновлении lstBattle, err=\n\t%v\n", err)
- сам.isEnd.Set()
- сам.Бот().КонтБот().Cancel()
- return
- }
- // sound.Shot()
- сам.Манёвр()
- }
- // Ищет урон от выстрела
- func (сам *выстрел) findDamage() {
- var (
- ind int
- еслиНайдено bool
- lstShot = сам.СписПолучить()
- strOut string
- )
- for ind, strOut = range lstShot {
- // <span class="yellow1 td_u">prospero tank</span>
- if strings.Contains(strOut, `<span class="yellow1 td_u">`+сам.login+`</span>`) {
- 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, ` на <span class="red1">`)
- 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 { // Кривой урон от выстрела
- сам.recharge.Dec5()
- // log._rintf("WARN Shot.findDamage(): ошибка в значении урона(%v)\n", iDamage)
- iDamage = 0
- }
- сам.damageSum += alias.АУрон(iDamage)
- // log._rintf("INFO Shot.Damage(): damageSum=%v\n", сам.damageSum)
- if iDamage < 70 {
- сам.damage.Set(alias.АУрон(iDamage))
- сам.recharge.Inc210()
- }
- // log._rintf("INFO Shot.findDamage(): выстрел=+%v, урон=%v", iDamage, сам.damageSum)
- if iDamage == 0 {
- return
- }
- сам.setDamage(alias.АУрон(iDamage))
- }
- // setDamage -- обновляет время перезарядки в зависимости от произведённого урона
- func (сам *выстрел) setDamage(val alias.АУрон) {
- сам.damage.Set(val)
- switch сам.damage.Result() {
- case "none":
- сам.recharge.Dec5()
- case "up":
- сам.recharge.Dec30()
- case "down":
- сам.recharge.Inc210()
- }
- }
- // IsEnd -- возвращает объект разрешения стрельбы
- func (сам *выстрел) IsEnd() ISafeBool {
- return сам.isEnd
- }
|